多态'get'使用hibernate,多对一,InheritanceType.JOINED

时间:2011-10-19 15:37:37

标签: hibernate inheritance polymorphism

我有类似的东西..

拥有多个座位的一个座位的汽车类。 Seat有一个子类LeatherSeat。

public class Car {
  private Seat seat;
  ...
  @ManyToOne(fetch = FetchType.LAZY)
  public Seat getSeat() {
    return seat;
  }
  ...
}

@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Seat {
  private String id;
  private String color;
} 

@Entity
public class LeatherSeat extends Seat {
    private String leatherType;
}

当我创建我的汽车并将我的汽车座椅设为LeatherSeat时,它会正确地保存在数据库上。当我想要获得我的Car(使用Criteria或Query列表)并且我读取getSeat()时,Seat始终只是一个座位,而不是一个LeatherSeat。我无法施放(例外),似乎必须通过id手动获取LeatherSeat。

这是使用JOINED继承类型的限制还是我遗漏了某些东西。如何将Seat作为LeatherSeat?

2 个答案:

答案 0 :(得分:2)

在LAZY案例中,座位将是“代理”,在实例化汽车时实例化。那时,Hibernate不知道座位是否是皮革。

当您遍历该属性并且它被延迟加载时,Hibernate将知道Seat是皮革,但它不能回溯地更改代理的类。但是,所有数据都在那里。如果您已经覆盖任何方法,座位将作为LeatherSeat响应。

如果您确实需要将此对象强制转换为LeatherSeat,则可以使用http://docs.jboss.org/hibernate/orm/3.2/api/org/hibernate/engine/PersistenceContext.html#unproxy(java.lang.Object取消装箱代理

请参阅此博客,详细了解为什么代理将始终为Seat,而不是LeatherSeat:http://sessionfactory.blogspot.co.uk/2010/08/hacking-lazy-loaded-inheritance.html

这里简要介绍了Hibernate文档:http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html#performance-fetching-proxies

答案 1 :(得分:1)

看起来,如果你做一个懒惰的提取,就像你正在使用getSeat一样,你将只获得父级,而不是子级。我尝试了与FetchType.EAGER相同的示例,并且getSeat正确返回LeatherSeat。

我不确定为什么hibernate在获取EAGER时可以获得带有LeatherSeat的Car,但是当进行LAZY获取时,hibernate似乎无法获得它。好像有什么东西在那里被打破了。

在InheritanceType.JOINED上有关于鉴别器列的故障单,其中有关于此方案的点。 https://hibernate.onjira.com/browse/ANN-140但是票据被拒绝,表明hibernate太优雅了,不需要InheritanceType.JOINED的鉴别器。然而,它无法在延迟提取上正确返回子类。

然后这个票据https://hibernate.onjira.com/browse/HHH-271?focusedCommentId=44089#comment-44089更具体地针对这个问题,那里的答案是“我们怎么想知道什么子类可以获得懒惰的提取?”

这两张票都很旧,被拒绝了。对我来说似乎是一个问题。但是现在您必须更改为不同的继承类型或使用eager fetch类型,因为这是根据hibernate的设计。