Самостоятельная ссылка на симметричную таблицу Hibernate Map с помощью @ManyToMany - PullRequest
2 голосов
/ 23 марта 2010

У меня есть следующий класс

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

Мне нужно создать таблицу карт, в которой элементы отображаются друг на друга в симметричных отношениях «многие ко многим».

@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 и другую для B на A.

Возможно ли это?

ОБНОВЛЕНИЕ: Спасибо за все предложения.
Когда я пытаюсь предложить предложение @ Pascal, две записи создаются следующим образом, когда я пытаюсь соединить элемент 1 с элементом 2.

FROM_ELEMENT_ID, TO_ELEMENT_ID
1, 2
2, 1

Я хочу, чтобы записи были симметричными, где 1,2 равно 2,1

Как решается эта проблема?

Обновление Я явно создал бин карты

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 и B, проверяя в таблице Connection записи, где
((от == A && до == B) || (от == B && до == A))
перед вставкой.

Ответы [ 3 ]

2 голосов
/ 24 марта 2010

При работе со многими ко многим вам не нужно слишком беспокоиться о дублировании, поскольку 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() приватным или пакетным.

0 голосов
/ 24 марта 2010

При работе с двунаправленными ссылками необходимо позаботиться о ссылке с обеих сторон и, цитируя документацию:

Многие разработчики программируют защиту и создают методы управления ссылками для правильной настройкиобе стороны.

Так что в вашем случае я бы предложил добавить следующие методы:

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);
}
0 голосов
/ 23 марта 2010

Эта проблема будет решена с помощью кэша первого уровня hibernate, чтобы отслеживать ссылки, пока вы отображаете m-2-m с обеих сторон.

...