Modeling many-to-many Relationship in JPA/Hibernat

2019-07-23 21:15发布

The schema is here: http://sqlfiddle.com/#!9/5ec63/2

or here; Query from many-to-many relationship

Now, I created the following classes:

  1. Student.java

    @Entity
    public class Student implements Serializable {
    
    @Id
    @GeneratedValue
    private int id;
    
    @NotNull
    @Size(min = 1, max = 35)
    private String name;
    
    public int getId() {
        return id;
    }
    
    public void setId(int id) {
        this.id = id;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    }
    
  2. Friend.java

    @Entity
    public class Friend implements Serializable {
    
    @EmbeddedId
    @NotNull 
    @ManyToMany( targetEntity = Student.class ) 
    private FriendPK primaryKey;
    
    
    public FriendPK getPrimaryKey() {
        return primaryKey;
    }
    
    public void setPrimaryKey(FriendPK primaryKey) {
        this.primaryKey = primaryKey;
    }
    }
    
  3. FriendPK.java

    @Embeddable
    public class FriendPK implements Serializable {
    
    @JoinColumn( name = "id_from", referencedColumnName = "id") 
    private int idFrom;
    
    @JoinColumn( name = "id_to", referencedColumnName = "id") 
    private int idTo;
    
    public FriendPK() {
    }
    
    public int getIdFrom() {
        return idFrom;
    }
    
    public void setIdFrom(int idFrom) {
        this.idFrom = idFrom;
    }
    
    public int getIdTo() {
        return idTo;
    }
    
    public void setIdTo(int idTo) {
            this.idTo = idTo;
        }
       }
    

1) Is this enough to model the many-to-many relationship? More specifically,

2) Do I need another "List friends" variable in Student class to store this student's friends?

3) Likewise, do I need another "List students" variable in Friend class to store students which are friends?

I vaguely feel the current design isn't enough, but can't figure out exactly what's needed.

Thank you.

2条回答
聊天终结者
2楼-- · 2019-07-23 21:30

Usually, to implement a many to many relation you need to use some middle table to map keys from two other tables.

In your case you need, say, t_students_friends table with two columns like the following:

t_students_friends

student_pk | friend_pk

In your entity classes you may need Lists for students and/or friends. Note that @ManyToMany also requires a @JoinTable annotation to work. If you want to access friends of a student, add to your Student class:

@ManyToMany
@JoinTable(
  name="t_students_friends",
  joinColumns=@JoinColumn(name="student_pk", referencedColumnName="id"),
  inverseJoinColumns=@JoinColumn(name="friend_pk", referencedColumnName="id"))
private List<Friend> friends;

You should also modify Friend class as follows. Add

@ManyToMany(mappedBy="friends")
private List<Student> students;

and use simple @Id int id field as you do in Students. There is no need in a FriendsPK class.

For more information you can read here, for example.

查看更多
Fickle 薄情
3楼-- · 2019-07-23 21:44

You need only one persistent to implement such schema. Hibernate will create a join table for @ManyToMany association. If you need to specify name of the join table you can use a @JoinTable annotation.

You don't need the Friend class. You can deal with friends with HQL or Criteria. So you don't need to know about a join table. Hibernate will add joins for a join table while converting HQL to SQL.

from Student s inner join fetch s.friends where s.name = :studentName

Keep in mind that it is HQL, for JPQL you need select.

@Table
@Entity
public class Student {

    @Id
    @GeneratedValue
    private int id;

    @NotNull
    @Size(min = 1, max = 35)        
    private String name;

    @ManyToMany
    private List<Student> friends = new ArrayList<Student>();

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Student> getFriends() {
        return friends;
    }

    public void setFriends(List<Student> friends) {
        this.friends = friends;
    }

}
查看更多
登录 后发表回答