2015-09-28 57 views
4

簡單的應用程序的工作原理錯下列實體結構Hibernate的繼承和2級高速緩存代理

@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類型(抽象類)的對象。

僞代碼:

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) 

在使用特殊的邏輯從緩存休眠構建實體加載: 現場它檢測由可變類型的類類型(它的EntityBase類),而不是鑑別器(最終類型[]類型= subclassPersister.getPropertyTypes();DefaultLoadEventListener)和呼叫方法
SessionImpl.internalLoad(字符串的entityName,序列化的ID,boolea Ñ心切,布爾可爲空的)女巫「實例化」從休眠緩存

它的工作原理相同的存儲在AbstractEntityPersister.EntityMetamodel holdedEntity 類型的懶惰&急切裝載抽象類和init字段由數據。它看起來像緩存的字段類型是靜態的,但它應該取決於字段的實例

如何解決它而不禁用休眠二級緩存?

的Hibernate 4.3.8(4.3.6 & 4.3.11也測試)

更新: test class

回答

3

這是因爲Hibernate使用懶惰協會代理。如果要禁用代理,您需要將@Proxy註釋添加到您的實體類的映射:

@Proxy(lazy=false) 

如果運行this GitHub test,你看到@Proxy(lazy=false)解決您的問題。

+0

但是從緩存中加載對象後,'holdedEntity'不是調試模式下的代理? –

+0

測試類已創建https://github.com/demon101/hibernate-l2-inheritence/blob/master/src/test/java/com/test/hibernate/L2InheritanceTest.java – demon101

+0

它的工作原理就像我告訴過你的。運行我在GitHub上上傳的測試。你可以在更新的答案中找到鏈接。 –