Hibernate inheritance and 2nd level cache proxies
简单的应用程序在以下实体结构中出现错误
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | @Entity(name="some_table") @Inheritance(strategy= InheritanceType.SINGLE_TABLE) @DiscriminatorColumn( name="TYPE", discriminatorType=DiscriminatorType.STRING ) abstract class EntityBase { @Id @GeneratedValue(strategy= GenerationType.AUTO) @Column private int id; } @Entity @DiscriminatorValue("EntityA") @Cacheable class EntityA extends EntityBase { @Column private int aColumn; ... } @Entity @DiscriminatorValue("EntityB") @Cacheable class EntityB extends EntityBase { @Column private int bColumn; ... } @Entity(name="holder_table") @Cacheable class HolderEntity { @Id @GeneratedValue(strategy= GenerationType.AUTO) @Column private int id; @ManyToOne(fetch=FetchType.LAZY) EntityBase holdedEntity; ... } |
对于第一次加载或没有缓存,一切正常
从缓存加载 HolderEntity 实例后,holdedEntity 字段由 EntityBase 类型的对象(抽象类)初始化。
伪代码:
1 2 3 4 | def a = HolderEntity.get(1) assert a.holdedEntity.class!=EntityBase //ok a = HolderEntity.get(1) // load from cache assert a.holdedEntity.class!=EntityBase //fails (actually EntityBase_$$_jvstbbe_0) |
在使用特殊逻辑从缓存hibernate构造实体加载期间:
对于字段,它通过变量类型(它的 EntityBase 类)而不是鉴别器(final Type[] types = subclassPersister.getPropertyTypes(); in DefaultLoadEventListener)检测类类型并调用方法
SessionImpl.internalLoad(String entityName, Serializable id, boolean eager, boolean nullable) 巫婆"实例化"抽象类和初始化字段来自hibernate缓存
懒惰也一样
这是因为 Hibernate 使用代理进行惰性关联。如果你想禁用代理,你需要在你的实体类映射中添加@Proxy注解:
1 |
如果你运行这个 GitHub 测试,你会看到