为了识别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);
}
}
{
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
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对象所关联的集合类属性。这样就解决了问题。