Hibernate - объект карты, принадлежащий двум другим объектам (объект с двумя родителями)

У меня возникли проблемы с отображением следующего:

public class Operation {
 private Integer id;
 private String name;
 private List<item> items = new ArrayList<item>();
 //set/getters/hashcode/etc. omitted
 public void addItem(Item i,Operation end) {
 i.setOperationStart(this);
 i.setOperationEnd(end};
 items.add(i);
 end.getItems().add(i);
 }
public class Item {
 private Integer id;
 private String name;
 private Operation operationStart;
 private Operation operationEnd;
 //set/getters/hashcode/etc. omitted
}
</item></item>

Таким образом, в основном операция имеет кучу элементов, а элемент принадлежит 2 операциям. Кроме того, нет смысла, чтобы элемент существовал, если один из Операций не существует, т.е. Если я удалю один из Операций, я хочу удалить элемент из того места, где он еще хранится.

Есть ли у кого-нибудь указатель на то, как я сопоставлял вышеуказанные классы, или мог бы указать мне на некоторые примеры, показывающие, как сопоставить дочерний объект с двумя родителями?

2 ответа

С объектно-ориентированной точки зрения представленное выглядит как два ManyToOne ассоциации между Item и Operation, one из них двунаправленные. Это можно было бы отобразить следующим образом:

@Entity
public class Item {
 @Id private Integer id;
 private String name;
 @ManyToOne
 private Operation operationStart;
 @ManyToOne
 private Operation operationEnd;
 //set/getters/hashcode/etc. omitted
}
@Entity
public class Operation {
 @Id private Integer id;
 private String name;
 @OneToMany(cascade = CascadeType.REMOVE, mappedBy="operationStart")
 private List<item> items = new ArrayList<item>();
 //set/getters/hashcode/etc. omitted
}
</item></item>

Это должно привести к тому, что таблица [ITEM] имеет два FK, указывающих на [OPERATION]. И заселение коллекции items приведет к ограничению SELECT к одному из них (ID операции начала в приведенном выше примере).

Я не знаю, имеет ли смысл этот сценарий, но это ИМО, с которым может справиться только Hibernate. Если это не то, что вы хотите, то я думаю, вы должны иметь две коллекции на стороне Operation (что вы могли бы спрятаться за дружественными методами).

Если вы используете hbm.xml или аннотации, это не имеет никакого значения.


Это звучит как сочетание отношения "многие-ко-многим" между элементами и операциями и тройной связи между одним элементом и двумя операциями.

Предполагая, что ваша бизнес-логика фиксирована ровно на две операции за элемент, и не более того, я бы решил эту проблему следующим образом:

  • Если вы хотите создать чистую объектную модель, создайте промежуточный объект для хранения ссылок на две операции, и он должен содержать один элемент в качестве компонента.
  • Сопоставьте элементы в hbm. В принципе, каждая операция должна иметь список промежуточного объекта, и каждый промежуточный объект имеет один элемент. Когда вы удаляете промежуточный объект, каскадируйте удаление с элементом, но не выполняйте операции.

Сложная часть, как вы сказали, - это когда вы удаляете операцию. Независимо от того, используете ли вы промежуточный объект или нет, вам необходимо каскадировать удаление в список с помощью all-delete-orphan. Однако я подозреваю, что у вас возникнут проблемы из-за кеша второго уровня. Единственный способ, который я знаю об этом, это:

  • перед удалением операции op1, пересечь граф объектов и отсоединить каждый промежуточный объект от его другой операции op2 и только затем выполнить промывку. В противном случае hibernate откажется удалить промежуточные объекты, поскольку они все еще хранятся в некоторых наборах в других операциях.

licensed under cc by-sa 3.0 with attribution.