Help me to understand how I can realize many to many self join with extra column using hibernate? Should I map join table too? Or may be exists another way? I can not find anything usefull for me...
2 Answers
Map the join table as a dedicated entity and then link it via two OneToMany
relationships. This often is the right way as it becomes more than just a technical detail as soon as you add more columns.
This should work the same way for a self join, you just have two fields on that model that are associated to the joining entity.
See this answer, where this is described in more detail.
I've been struggling with this question for a long time, perhaps someone will find Wolfram's wording difficult, so I'll explain it in more detail: Imagine, what we need map something like that uml_diagramm
I needed to set up links between any two users, and the links were used to chat between them. So our user class will be :
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
@Entity
public class User implements Serializable {
private String email;
private String password;
private Long id;
private String nickname;
private String phone;
private Collection<Chats> chatsById;
private Collection<Chats> chatsById_0;
@Basic
@Column(name = "email", nullable = false, length = -1)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Basic
@Column(name = "password", nullable = false, length = -1)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Id
@Column(name = "id", nullable = false)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Basic
@Column(name = "nickname", nullable = true, length = -1)
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
@Basic
@Column(name = "phone", nullable = true, length = -1)
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(email, user.email) && Objects.equals(password, user.password) && Objects.equals(id, user.id) && Objects.equals(nickname, user.nickname) && Objects.equals(phone, user.phone);
}
@Override
public int hashCode() {
return Objects.hash(email, password, id, nickname, phone);
}
@OneToMany(mappedBy = "userByIdFrom")
public Collection<Chats> getChatsById() {
return chatsById;
}
public void setChatsById(Collection<Chats> chatsById) {
this.chatsById = chatsById;
}
@OneToMany(mappedBy = "userByIdTo")
public Collection<Chats> getChatsById_0() {
return chatsById_0;
}
public void setChatsById_0(Collection<Chats> chatsById_0) {
this.chatsById_0 = chatsById_0;
}
}
Please, pay attention to two @OneToMany annotations - getChatsById and getChatsById_0
Now our Chat class:
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
@Entity
@IdClass(ChatsPK.class)
public class Chats implements Serializable {
private Long idFrom;
private Long idTo;
private Object uuid;
private User userByIdFrom;
private User userByIdTo;
@Id
@Column(name = "id_from", nullable = false)
public Long getIdFrom() {
return idFrom;
}
public void setIdFrom(Long idFrom) {
this.idFrom = idFrom;
}
@Id
@Column(name = "id_to", nullable = false)
public Long getIdTo() {
return idTo;
}
public void setIdTo(Long idTo) {
this.idTo = idTo;
}
@Basic
@Column(name = "uuid", nullable = false)
public Object getUuid() {
return uuid;
}
public void setUuid(Object uuid) {
this.uuid = uuid;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Chats chats = (Chats) o;
return Objects.equals(idFrom, chats.idFrom) && Objects.equals(idTo, chats.idTo) && Objects.equals(uuid, chats.uuid);
}
@Override
public int hashCode() {
return Objects.hash(idFrom, idTo, uuid);
}
@ManyToOne
@JoinColumn(name = "id_from", referencedColumnName = "id", nullable = false)
public User getUserByIdFrom() {
return userByIdFrom;
}
public void setUserByIdFrom(User userByIdFrom) {
this.userByIdFrom = userByIdFrom;
}
@ManyToOne
@JoinColumn(name = "id_to", referencedColumnName = "id", nullable = false)
public User getUserByIdTo() {
return userByIdTo;
}
public void setUserByIdTo(User userByIdTo) {
this.userByIdTo = userByIdTo;
}
}
To be honest, I haven't figured out why it works yet myself but, there should be more details
Meanwhile, I know for a fact that intelijIdea can generate you models from the database and this may be help you Generate Persistence Mapping by Database Schema - Detail settings for Entity Class. (This code was generated by it )

- 51
- 2
- 7