Skip to content

hibernate子类与代理延迟加载 问题

公司CRMClient 与 CRMPersonal 为继承关系 但是在返回为父对象的时候死活不能转换成子对象.

一直怀疑是hibernate代理的问题.查了单文献.找到这个.问题解决.学习一下吧~

一个超类Task,有几个子类如 EntryTask和GroupTask,对应同一张数据库表,用一个discriminator字段来区分是哪一个子类。

在需要判断hibernate返回的对象是哪一个子类时遇到麻烦,如果返回的不是代理对象,使用if(task instanceof EntryTask)这样的语句就可以,但是如果是代理对象就有问题了,因为其他地方有对Task的多对一关联,并且关联处指定的父类肯定是Task超 类,不会去指定具体哪个子类,这样一旦延迟加载生成的是Task类的代理对象。

该对象只instanceof Task类,而不是它的任何子类,即使在加载了实体类数据后,该代理对象的类属性也不会改变,仍旧只instanceof Task超类,而且在其他地方查询时,对于相同的id,hibernate返回的还是以前返回过的代理对象(hibernate会保持返回的一致性)。

当然要判断该代理对象到底是哪个具体子类还是有办法的,可以在Task超类中加一个只读的discriminator属性,通过 discriminator判断该代理对象是哪个子类,但是象EntryTask entryTask = (EntryTask)task这样的转换还是不行的,java只知道它是个Task,除非再通过id来load或get,如:

  1. EntryTask entryTask = (EntryTask)session.get(EntryTask.class,task.getId())

还有一种直接的方法,就是直接获得被代理的实体对象,hibernate生成的代理对象都实现了HibernateProxy接口,该接口提供了获取被代理对象的方法,可以这样来获取:

  1. Object target = ((HibernateProxy)task).getHibernateLazyInitializer().getImplementation()

这样就可以进行类的比较转换了,这种方法虽然不复杂,但还是觉得罗唆。

现在的解决办法是不使用延迟加载,设置Task类映射lazy=”false”,并且在查询时使用eager-fetch,这样它就不会返回代理对象了,对我们这个应用来说性能影响也不大。

发表评论

电子邮件地址不会被公开。 必填项已用*标注