Hibernate - 属于另外两个对象的映射对象(具有2个父对象的对象)

时间:2010-08-22 19:31:15

标签: java hibernate orm

我在绘制以下内容时遇到了一些麻烦:

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
}

所以基本上一个Operation有一堆Items,一个Item属于2个Operations。 此外,如果其中一个操作不存在,则项目存在没有意义,即,如果我删除其中一个操作,我想从其存储的任何地方删除该项目。

有没有人指出我如何映射上面的类,或者可以指出一些示例来说明如何映射具有2个父项的子对象?

2 个答案:

答案 0 :(得分:2)

从面向对象的角度来看,所表示的内容与ManyToOneItem之间的两个 Operation关联相似,一个他们是双向的。这可以像这样映射:

@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]表有两个指向[OPERATION]的FK。填充items集合会导致SELECT仅限于其中一个(上例中的ID启动操作。)

我不知道这种情况是否有意义,但这是IMO Hibernate可以处理的唯一场景。如果这不是您想要的,那么我认为您应该在Operation方面有两个集合(您可以隐藏在友好方法之后)。

无论使用hbm.xml还是注释都没有任何区别。

答案 1 :(得分:1)

这听起来像是项目和操作之间多对多关系的组合,以及一个项目和两个操作之间的三元关系。

假设您的业务逻辑仅针对每个项目的两个操作进行修复,而不是更多,我将按如下方式解决此问题:

  • 如果你想要一个干净的对象模型,那么创建一个中间对象来保存对这两个操作的引用,它应该把一个项目作为一个组件。
  • 映射hbm中的项目。基本上,每个Operation应该有一个中间对象的列表,每个中间对象都有一个Item。删除中间对象时,将删除级联到项目,而不是级联操作。

正如你所说,棘手的部分是你删除一个操作。无论您是否使用中间对象,都需要使用all-delete-orphan将删除级联到列表中。但是,我怀疑你会因为二级缓存而遇到一些问题。我知道的唯一方法就是:

  • 在删除操作op1之前,遍历对象图并将每个中间对象与其他操作op2分离,然后才刷新。否则,hibernate将拒绝删除中间对象,因为它们仍保留在其他操作中的某些集合中。