35

I need to create a join table in my database using JPA annotations so the result will be this:

enter image description here

So far I just implemented 2 entities:

@Entity
@Table(name="USERS", schema="ADMIN")
public class User implements Serializable {

    private static final long serialVersionUID = -1244856316278032177L;
    @Id 
    @Column(nullable = false)
    private String userid;  
    
    @Column(nullable = false)
    private String password;

    public String getUserid() {
        return userid;
    }

    public void setUserid(String userid) {
        this.userid = userid;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
    
}

@Entity
@Table(name="GROUPS", schema="ADMIN")
public class Group implements Serializable {

    private static final long serialVersionUID = -7274308564659753174L;
    @Id
    @Column(nullable = false)
    private String groupid;
    
    public String getGroupid() {
        return groupid;
    }
    public void setGroupid(String groupid) {
        this.groupid = groupid;
    }
}

Should i create another entity called USER_GROUP or i can just add some annotations, so the join table will be created automatically when i run create tables from entities(ORM)?

How should i annotate my entities to achieve the same as in the image?

Community
  • 1
  • 1
javing
  • 12,307
  • 35
  • 138
  • 211
  • 2
    What is cardinality between Group and User entities? Is it @OneToMany, so that each group has 0..* users? Or is it ManyToMany? – jFrenetic Nov 02 '11 at 11:18
  • 1
    It is a @OneToMany, so that each group has 0..* users, as you said.A user must belong to one and just one group, but a group can have many(0..*) users. – javing Nov 02 '11 at 11:25

4 Answers4

43

You definitely shouldn't create User_Group entity as it's more the underlying database representation than the object oriented one.

You can achieve the join table by defining something like:

@Entity
@Table(name="USERS", schema="ADMIN")
public class User implements Serializable {
//...

@ManyToOne
@JoinTable(name="USER_GROUP")
Group group;

@Entity
@Table(name="GROUPS", schema="ADMIN")
public class Group implements Serializable {
//...

@OneToMany(mappedBy="group")
Set<User> users;

Edit: If you want to explicitly set the names of the columns you could use @JoinColumn elements as shown below:

@ManyToOne
@JoinTable(name="USER_GROUP",
    joinColumns = @JoinColumn(name = "userid", 
                              referencedColumnName = "userid"), 
    inverseJoinColumns = @JoinColumn(name = "groupid", 
                              referencedColumnName = "groupid"))
Group group;
Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
Piotr Nowicki
  • 17,914
  • 8
  • 63
  • 82
  • Did you mean @ManyToMany? http://download.oracle.com/javaee/5/api/javax/persistence/ManyToMany.html – Jonathan Nov 02 '11 at 12:09
  • 1
    @Jonathan no I mean `@OneToMany` and `@ManyToOne` as shown in the example. Why? – Piotr Nowicki Nov 02 '11 at 12:11
  • @PedroKowalski Wasn't sure, because they take the same parameters, but `@ManyToMany` seems to also express the relationship he was looking for. – Jonathan Nov 02 '11 at 12:16
  • @Jonatan, no I don't think it express the relationship the OP wanted. "each group has 0..* users, as you said. A user must belong to `one and just one group`, but a group can have many(0..*) users. " – Piotr Nowicki Nov 02 '11 at 12:19
  • Question: what if i have already this additional table? The JoinTable wont overwrite the existign one right? – TheWandererr Sep 22 '17 at 16:04
6

I would implement it this way:

@Entity
@Table(name="GROUPS", schema="ADMIN")
public class Group implements Serializable {
  @OneToMany
  @JoinTable(name = "USER_GROUP",
            joinColumns = @JoinColumn(name = "groupid"),
            inverseJoinColumns = @JoinColumn(name = "userid"))
  private List<User> users;
}

Solution suggested by @PedroKowalski should work too, but then you'll have to keep a reference to Group entity in your User entity which is not always possible.

jFrenetic
  • 5,384
  • 5
  • 42
  • 67
  • Well, it really depends on if you want to have a uni- or bi-directional relationship. I assumed bidirectional, as it seemed reasonable for User to know to which Group he belongs and for Group to know what Users are within it. Of course if unidirectional relationship is required, than this solution is also fine. – Piotr Nowicki Nov 02 '11 at 12:17
6

To have the same annotations like in your diagram you can do this in your User class:

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "USER_GROUP", 
           joinColumns = { @JoinColumn(name = "userid") }, 
           inverseJoinColumns = { @JoinColumn(name = "groupid") })
private List<Group> grups;

in your group class

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "USER_GROUP", 
           joinColumns = { @JoinColumn(name = "groupid") }, 
           inverseJoinColumns = { @JoinColumn(name = "userid") })
private List<User> users;
Cedriga
  • 3,860
  • 2
  • 28
  • 21
user902383
  • 8,420
  • 8
  • 43
  • 63
  • Why many to many? A user must belong to one and just one group? But a group can have more than one user. I know it sounds rare, but it has to be that way. It is not like facebook where a user can be in many groups, the group means the role of that user in the system. And a user can only have one role. – javing Nov 02 '11 at 12:18
  • Question: what if i have already this additional table? The JoinTable wont overwrite the existign one right? – TheWandererr Sep 23 '17 at 17:38
  • @TheWandererr if you have existing table, then what you need to do is, set name to be name of your table and names of joined columns. then jpa will use it. as for overwrite, in which sense you mean? if relations between entities will change, then jpa will change data in database – user902383 Sep 25 '17 at 07:50
0

I'm wondering what is the point to create a Join Table in this way, considering that we can't access directly for queries? JPA doesn't allow to make queries directly to the Join Table, so if the user want to do an operation on USER_GROUP, he has to creare a normal join query between users and groups; due to this, the join table USER_GROUP is useless.

Angel
  • 31
  • 8
  • Angel, that's the whole point of JPA. In this instance you don't have to write the query for it, as everything is represented as an object. Let's assume you have a USER Entity, and a COURSE Entity. A User can have multiple Courses, and a Course can be assigned to multiple Users. (Many to Many relation, right?) So you want to list a specific user's courses which is defined as a variable (probably List) at the User Entity. In this case you just look up for the user, and you can call the getter() of the list, which will give you back their courses. You can see that the join table is being used. – Mr.Fireman Mar 28 '17 at 08:18