2015-02-08 63 views
0

我正在升級到Hibernate 4.3.8,並在單元測試中遇到了一個奇怪的問題。休眠升級後不能寫只讀對象

我引用一個語言類

public class User{ 
    @ManyToOne(cascade=CascadeType.MERGE,optional = true, fetch=FetchType.EAGER) 
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 
    @Fetch(FetchMode.SELECT) 
    private Language language; 

    @Column 
    @NaturalId(mutable=false) 
    private String email; 

} 

@Entity 
@Immutable 
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY) 
@NaturalIdCache(region=CacheRegion.NATURAL) 
public class Language{ 

} 

因此用戶類,升級後,我開始看到這個異常的用戶類加載這樣的:

User user = (User) getSessionFactory().getCurrentSession() 
    .bySimpleNaturalId(User.class) 
    .load(email); 

例外:

java.lang.UnsupportedOperationException: Can't write to a readonly object 
    at org.hibernate.cache.ehcache.internal.strategy.ReadOnlyEhcacheEntityRegionAccessStrategy.update(ReadOnlyEhcacheEntityRegionAccessStrategy.java:115) 
    at org.hibernate.cache.ehcache.internal.nonstop.NonstopAwareEntityRegionAccessStrategy.update(NonstopAwareEntityRegionAccessStrategy.java:216) 
    at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:211) 
    at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:144) 
    at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.performTwoPhaseLoad(AbstractRowReader.java:244) 
    at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:215) 
    at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:140) 
    at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:138) 
    at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:102) 
    at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:186) 
    at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4126) 
    at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:503) 
    at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:468) 
    at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:213) 
    at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:275) 
    at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:151) 
    at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1070) 
    at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:989) 
    at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:716) 
    at org.hibernate.type.EntityType.resolve(EntityType.java:502) 
    at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:170) 
    at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:144) 
    at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.performTwoPhaseLoad(AbstractRowReader.java:244) 
    at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:215) 
    at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:140) 
    at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:138) 
    at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:102) 
    at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:186) 
    at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4126) 
    at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:503) 
    at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:468) 
    at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:213) 
    at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:275) 
    at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:151) 
    at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1070) 
    at org.hibernate.internal.SessionImpl.access$2000(SessionImpl.java:176) 
    at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2551) 
    at org.hibernate.internal.SessionImpl$SimpleNaturalIdLoadAccessImpl.load(SessionImpl.java:2794) 

此處有任何建議嗎?

回答

0

因此,這似乎是因爲在某個地方發生,當涉及到緩存時,Hibernate開始處理與在不同事務中創建的對象相同的事務中創建的對象。因此,如果你有一個單元測試,你在創建只讀對象的事務中做了一些設置,即使你只寫了一次對象,如果它們是在與測試相同的事務中創建的,它們也會拋出一個異常。

解決方法是使用具有Propagation.REQUIRES_NEW的事務管理器在集中方法中創建一次性只讀對象。您不能對此使用批註,BTW