java - 奇怪的 NullPointerException 与 Hibernate 并获取类型 LAZY
问题描述
在我们的应用程序中,我想生成一份报告。因此加载了多个实例Foo
和关联Bar
实体(但未更改)。相关数据取自实体并存储在报告 bean 中以用于实际报告生成。当事务关闭并且 Hibernate 刷新错误发生时(见下文)。
除了其他属性之外,Foo
还包含对 的引用 Bar
。这是两个类的摘录:
@Entity
@Table(name = "FOO")
public class Foo {
@Column(name = "BAR_ID")
private Long barId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(insertable = false, updatable = false)
private Bar bar;
public Long getBarId() {
return barId;
}
public void setBarId(Long barId) {
this.barId = barId;
}
public Bar getBar() {
return bar;
}
// no setter for "bar"
// other attributes
}
@Entity
@Table(name = "BAR")
public class Bar {
@OneToMany(mappedBy = "bar", fetch = LAZY)
private List<Foo> foos;
// no getter/setter for "foos"
// other attributes
}
具有各种其他操作(包括创建、编辑、删除上述实体)的整个应用程序完美无缺,但在创建报告时出现奇怪的错误:
1)
org.springframework.orm.hibernate4.HibernateSystemException: Found two representations of same collection: Bar.foos; nested exception is org.hibernate.HibernateException: Found two representations of same collection: Bar.foos
at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:216)
at org.springframework.orm.hibernate4.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:681)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:563)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
at de.ba.wws.aop.TransactionTimeAspect.setTransactionTime(TransactionTimeAspect.java:20)
[...]
Caused by: org.hibernate.HibernateException: Found two representations of same collection: Bar.foos
at org.hibernate.engine.internal.Collections.processReachableCollection(Collections.java:170)
at org.hibernate.event.internal.FlushVisitor.processCollection(FlushVisitor.java:59)
at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:121)
at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:82)
at org.hibernate.event.internal.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:76)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:172)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:231)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:102)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:55)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:555)
... 119 more
2)
java.lang.NullPointerException
at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:155)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:91)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:55)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:555)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
at de.ba.wws.aop.TransactionTimeAspect.setTransactionTime(TransactionTimeAspect.java:20)
[...]
3)NullPointerException
在org.hibernate.internal.util.compare.ComparableComparator.compare(Comparable, Comparable)
(两个参数null
)。(我无法为此提供堆栈跟踪,因为在撰写本文时我无法生成它。)
在执行报告时,我得到了上述三个错误之一(或根本没有错误)。有时我需要多次调用报告才能产生错误,有时第一次运行就已经产生了一个错误。我无法弄清楚可能导致这种行为的原因。
我发现的唯一解决方法是将两个显示属性的获取类型切换为EAGER
. 然后一切正常,但由于预取的数据量很高,所以不理想。
欢迎每一个提示,如果您需要更多详细信息,请告诉我。
我们目前使用的是 Hibernate 4.3.8。我在本地尝试了较新的版本(4.3.11 显示相同的问题),但升级到 5.x 是一项主要任务,如果有人可以向我们保证问题已得到解决(如果它实际上是 Hibernate,则只能在很短的时间内完成)问题)在 5.x 中。
解决方案
好的,我终于明白了问题是什么:
由于数据量大,生成报表需要花费大量时间,因此生成是并行的。在执行程序线程的处理部分中,一些对象是从bean
--- 实际上仍然是Hibernate
托管实体--- 中引用的,并且Hibernate
无法解析这些对象proxies
(因为在session
内部无效threads
)。
奇怪的是,这些问题(实际上是真正的异常!)在将Hibernate
日志记录设置为时才可见,trace
并且产生的异常不像基础异常那么容易理解!
这也解释了为什么当 fetch 模式设置为EAGER
.
我现在的解决方案是确保在实际多线程处理之前beans
从实体(在 中)获取所有需要的数据。
推荐阅读
- ios - 如何将collectionview的索引路径访问到tableview
- enums - 检查枚举上的 PartialEq 而不检查变体的附加数据
- css - 如果条件基于 CSS 样式
- javascript - 关于 JavaScript 中 Object.create() 和“new”方法的输出的问题
- node.js - 如何使用 CryptoJS 在 Angularjs 中加密和在 Nodejs 中解密
- javascript - Javascript:使用 querySelectorAll 查找匹配特定条件的所有输入元素
- angular - 为什么我不能设置 PrimeNG p-calenar 组件 CSS 样式?
- iis - 如何在 Windows server 2012 r2 上为 websphere 上托管的应用程序创建自签名证书
- reactjs - 使用鼠标拖放选择形状不起作用 - React Konva
- unix - 如何修剪前导和尾随空格并将其替换为 tab(/t) 以使其从文件的每一行组织起来?