使用@ManyToMany自引用对称Hibernate映射表

时间:2010-03-23 15:44:20

标签: java hibernate orm many-to-many jointable

我有以下课程

public class ElementBean {
 private String link;
 private Set<ElementBean> connections;
}

我需要创建一个map表,其中元素以多对多的对称关系相互映射。

@ManyToMany(targetEntity=ElementBean.class)
@JoinTable(
    name="element_elements",
    joinColumns=@JoinColumn(name="FROM_ELEMENT_ID", nullable=false),
    inverseJoinColumns=@JoinColumn(name="TO_ELEMENT_ID", nullable=false)
)
public Set<ElementBean> getConnections() {
    return connections;
}

我有以下要求

当元素A被添加为元素B的连接时,元素B应该成为元素A的连接。所以A.getConnections()应该返回B而B.getConnections()应该返回A.我不想显式创建2条记录,一条用于映射A到B,另一条用于映射到A。

这可能吗?

更新:感谢您提出的所有建议 当我尝试@ Pascal的建议时,当我尝试将元素1与元素2连接时,会创建两条记录。

FROM_ELEMENT_ID,TO_ELEMENT_ID
1,2 2,1,

我希望记录是对称的,其中1,2与2,1

相同

这个问题是如何处理的?

更新的 我明确地创建了一个map bean

class ConnectionBean {
    ElementBean from;
    ElementBean to;
}

@NotNull
@ManyToOne
@JoinColumn(name="FROM_ELEMENT_ID", nullable=false)
public ElementBean getFrom() {
    return from;
}

@NotNull
@ManyToOne
@JoinColumn(name="TO_ELEMENT_ID", nullable=false)
public ElementBean getTo() {
    return to;
}

我将ElementBean更新为

public class ElementBean {
    private String link;
    private Set<ConnectionBean> from;
    private Set<ConnectionBean> to;
}

@OneToMany(mappedBy="from", fetch=FetchType.LAZY)
public Set<ConnectionBean> getFrom() {
    return from;
}

@OneToMany(mappedBy="to", fetch=FetchType.LAZY)
public Set<ConnectionBean> getTo() {
    return to;
}

在这里我可以控制插入和删除。例如,在插入新的ConnectionBean之前,我检查元素A和A之间是否存在连接。 B通过检查连接表中的记录     ((从== A&amp;&amp;到== B)||(从== B&amp;&amp;到== A))
在插入之前。

3 个答案:

答案 0 :(得分:1)

当处理多对多时,您不必过于担心重复,因为hibernate会为您处理。您必须担心确保对象模型是一致的,而hibernate不一定有助于此。

在你的“addConnection”方法中 - 你不应该有一个返回实际连接的getConnections方法,而是返回一个就绪版本,你需要确保你处理关系的两个方面

addConnection(ElementBean element) {
    if (element ==null) { 
        throw new IllegalArgumentException("cannot add null element"); 
    }
    connections.add(element);
    element.getConnections0().add(this);
}

这意味着您的要求将保留,当它保存时,它将保存正常。它不会保存两次,因为它会注意到一个是另一个的后引用。 您应该将getConnections0()设为私有或包。

答案 1 :(得分:0)

这将通过hibernate的第一级缓存来解决,只要您从两侧映射m-2-m,就可以跟踪引用。

答案 2 :(得分:0)

使用双向链接时,您需要处理双方的链接,并引用文档:

许多开发人员采取防御措施并创建链接管理方法以正确设置双方。

所以在你的情况下,我建议添加以下方法:

public Set<ElementBean> getConnections() {
    return connections;
}

public void setConnections(Set<ElementBean> connections) {
    this.connections = connections;
}

public void addToConnection(ElementBean connection) {
    this.getConnections().add(connection);
    connection.getConnections().add(this);
}

public void removeFromConnection(ElementBean connection) {
    this.getConnections().remove(connection);
    connection.getConnections().remove(this);
}