0

I'm a newbie to JPA and Hibernate. I was able to set up some small basic examples as expected. Now I'm trying to use it for a first real world project. Studying the Hibernate best practices I found that you should avoid many-to-many relationships. I found relating questions here and I do understand the concept why not to use it but I'm not understanding how it should be implemented.

So when I have the often used example of a user that can the part of many groups and a group that does have many users, how to implement that. So this is a many-to-many relationship. But I should not use many-to-many, as far as I understood because it is very likely that I will need other information in the future, like a specific role a user has in a group or a date when he joined. So I use a two one-to-many relationships and a joining table which doesnt only contains the ids but also will contain additional information like role or date. Is that right? And then neither the class group has a property users nor the class users has a property groups both have a property joinTableEntries?

Did I get the concept right so far?

@Entity
@Table(name="user")
public class User {



    private int userId;
    private String username;
    private Set<JTUserGroup> jtUserGroupSet=new HashSet<JTUserGroup>(0);


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "userid")
    public int getUserId()
    {
        return this.userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
    public Set<JTUserGroup> getJtUserGroupSet() {
        return jtUserGroupSet;
    }


    public void setJtUserGroupSet(Set<JTUserGroup> jtUserGroupSet) {
        this.jtUserGroupSet = jtUserGroupSet;
    }
}

@Entity
@Table(name = "forumgroup")
public class Group {

    private int groupId;
    private String groupname;
    private Set<JTUserGroup> jtUserGroupSet=new HashSet<JTUserGroup>(0);

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "groupid")
    public int getGroupId() {
        return groupId;
    }

    public void setGroupId(int groupId) {
        this.groupId = groupId;
    }

    public String getGroupname() {
        return groupname;
    }

    public void setGroupname(String groupname) {
        this.groupname = groupname;
    }

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "group")
    public Set<JTUserGroup> getJtUserGroupSet() {
        return jtUserGroupSet;
    }

    public void setJtUserGroupSet(Set<JTUserGroup> jtUserGroupSet) {
        this.jtUserGroupSet = jtUserGroupSet;
    }


}

@Entity
@Table(name = "jtusergroup")
public class JTUserGroup {
    private int joinId;
    private User user;
    private Group group;`enter code here`

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public int getJoinId() {
        return joinId;
    }

    public void setJoinId(int joinId) {
        this.joinId = joinId;
    }


    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "userid", nullable = false)
    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "groupid", nullable = false)
    public Group getGroup() {
        return group;
    }

    public void setGroup(Group group) {
        this.group = group;
    }

}

and then to use these I add a new user to a group like this:

User user1=new User();
        User user2=new User();
        User user3=new User();
        Group group1=new Group();
        Group group2=new Group();


        user1.setUsername("Mark");
        user2.setUsername("Anton");
        user3.setUsername("Maggy");
        group1.setGroupname("Mark_Maggy");
        group2.setGroupname("Maggy_Anton");

        JTUserGroup jt1=new JTUserGroup();
        jt1.setGroup(group1);
        jt1.setUser(user1);


        JTUserGroup jt2=new JTUserGroup();
        jt2.setGroup(group1);
        jt2.setUser(user3);


        JTUserGroup jt3=new JTUserGroup();
        jt3.setGroup(group2);
        jt3.setUser(user3);


        JTUserGroup jt4=new JTUserGroup();
        jt4.setGroup(group2);
        jt4.setUser(user2);


        GenericDAO<JTUserGroup> jtDao=new GenericDAO<JTUserGroup>();

        jtDao.beginTransaction();
        jtDao.insert(jt1);
        jtDao.insert(jt2);
        jtDao.insert(jt3);
        jtDao.insert(jt4);
        jtDao.commit();

1 Answers1

0

Just image this, you have User and let's say that Group is extending your user. Now your 'Group' has a sub-class which is JTUserGroup. Let's say that User has one-to-many relationship with Group (based on your logic, user can belong on many groups). Now the question, how can User know about JTUserGroup? You need somehow to get FK(as everybody knows that FK creates assosiations with classes) in your User class to know about all your 'Group' sub-classes and rely on logic, belong (let's say) for a several sub-classes which belongs to 'Group'. It is not impossible to do it or you need to make complex solutions to implement it, and what about SQL queries - it will look very complex. So you need to handle it somehow - the solution is inheritance. Doing this you can create associations between classes in very easy way. If you will not have many info (or let's say complex tables schema with a lot of info) you can use SINGLE_TABLE strategy. If there will be a lot of info/columns(in your tables), your data will not be normalized with this strategy so better use JOINED or TABLE_PER_CONCRETE_CLASS strategy.

solvator
  • 371
  • 1
  • 6
  • 12