解決問題(十)——HashCodeBuilder在one-to-many關係中出現Lazy異常

爲了識別po對象中,通常都會用po對象繼承一個BaseObject基類,小弟也是如此做法,基類是從網上找到的一個比較好的範例。

public class BaseObject implements Serializable 
{
    
private static final long serialVersionUID = -1540986753080346874L;

    
public String toString() 
    {
        
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
    }
    
    
public boolean equals(Object o) 
    {
        
return EqualsBuilder.reflectionEquals(this, o);
    }
    
    
public int hashCode() 
    {
        
return HashCodeBuilder.reflectionHashCode(this);
    }
}

 

代碼本身並沒有什麼問題,但是如果某個po對象包含關聯屬性,比如說Set,那麼在進行懶加載後就會有以下異常。

org.hibernate.LazyInitializationException: illegal access to loading collection
    at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:
341)
    at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:
86)
    at org.hibernate.collection.PersistentSet.hashCode(PersistentSet.java:
411)
    at org.apache.commons.lang.builder.HashCodeBuilder.append(HashCodeBuilder.java:
856)
    at org.apache.commons.lang.builder.HashCodeBuilder.reflectionAppend(HashCodeBuilder.java:
174)
    at org.apache.commons.lang.builder.HashCodeBuilder.reflectionHashCode(HashCodeBuilder.java:
348)
    at org.apache.commons.lang.builder.HashCodeBuilder.reflectionHashCode(HashCodeBuilder.java:
387)
    at com.coolcate.model.BaseObject.hashCode(BaseObject.java:
33)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
    at java.lang.reflect.Method.invoke(Method.java:
585)
    at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:
157)
    at com.coolcate.model.vo.Restaurant$$EnhancerByCGLIB$$7e0832e8.hashCode(
<generated>)
    at org.apache.commons.lang.builder.HashCodeBuilder.append(HashCodeBuilder.java:
856)
    at org.apache.commons.lang.builder.HashCodeBuilder.reflectionAppend(HashCodeBuilder.java:
174)
    at org.apache.commons.lang.builder.HashCodeBuilder.reflectionHashCode(HashCodeBuilder.java:
348)
    at org.apache.commons.lang.builder.HashCodeBuilder.reflectionHashCode(HashCodeBuilder.java:
387)
    at com.coolcate.model.BaseObject.hashCode(BaseObject.java:
33)
    at java.util.HashMap.put(HashMap.java:
418)
    at java.util.HashSet.add(HashSet.java:
194)
    at java.util.AbstractCollection.addAll(AbstractCollection.java:
318)
    at org.hibernate.collection.PersistentSet.endRead(PersistentSet.java:
329)
    at org.hibernate.engine.loading.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:
237)
    at org.hibernate.engine.loading.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:
222)
    at org.hibernate.engine.loading.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:
195)
    at org.hibernate.loader.Loader.endCollectionLoad(Loader.java:
877)
    at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:
865)
    at org.hibernate.loader.Loader.doQuery(Loader.java:
729)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:
236)
    at org.hibernate.loader.Loader.loadCollection(Loader.java:
1994)
    at org.hibernate.loader.collection.BatchingCollectionInitializer.initialize(BatchingCollectionInitializer.java:
52)
    at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:
565)
    at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:
60)
    at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:
1716)
    at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:
344)
    at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:
86)
    at org.hibernate.collection.PersistentSet.toArray(PersistentSet.java:
171)
    at com.coolcate.test.RestaurantTest.testSelectAllSubRestaurant(RestaurantTest.java:
55)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
    at java.lang.reflect.Method.invoke(Method.java:
585)
    at junit.framework.TestCase.runTest(TestCase.java:
168)
    at junit.framework.TestCase.runBare(TestCase.java:
134)
    at junit.framework.TestResult$
1.protect(TestResult.java:110)
    at junit.framework.TestResult.runProtected(TestResult.java:
128)
    at junit.framework.TestResult.run(TestResult.java:
113)
    at junit.framework.TestCase.run(TestCase.java:
124)
    at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:
130)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:
38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:
460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:
673)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:
386)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner

 

對於具體原因,也不是很清楚。但是根據錯誤堆棧判斷,是在構建hashCode時加入了關聯屬性,由此激活了懶加載。在我的測試代碼中,在沒有調用hashCodeBuilder之前已經激活了懶加載,之後又調用hashCodeBuilder引起二次加載,導致以上錯誤。這些沒有什麼依據,僅僅是推測。基於這個推測,我去掉了BaseObject,手動在每個po對象中重載equals和hashCode方法,方法中只是包含po對象的屬性,不包含po對象所關聯的集合類屬性。這樣就解決了問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章