Reputation: 1591
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...
Upvotes: 0
Views: 2222
Reputation: 61
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 )
Upvotes: 0
Reputation: 8052
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.
Upvotes: 1