解决问题(十)——HashCodeBuilder在one-to-many关系中出现Lazy异常

本文探讨了在使用Hibernate框架时,如何解决因POJO对象继承BaseObject基类而导致的懒加载异常问题。通过手动重写equals和hashCode方法,排除关联集合属性,成功避免了异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码匠君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值