可以看下这里 https://forum.hibernate.org/viewtopic.php?f=1&t=1008222 重点这句 The error message indicates that something is happening during the flush that causes non-initialized lazy objects to be initialized. 是不是和customer关联的迟加载对象因为某些原因未被初始化的缘故org.hibernate.AssertionFailure: collection [???] was not processed by flush() 这句话的意思想必也是collection没有在flush方法中被处理,因此报错
Course course = (Customer) postUpdateEvent.getEntity();
你上面这句是想获得course对象吧(算符优先级有问题,假定这里没问题,只是笔误),你尝试下在每次插入Message对象的时候,执行commit操作,即让session进行flush。
for(Customer cstm:customers){
Message msg = new Message();
msg.setTitle("..");
msg.setContent("课程时间已经调整到"+course.date);
msg.setCustomer(cstm);
messageDAO.create(msg);
//make sure the message is flushed by hibernate session here.
//something like session.flush();
}
我猜测错误的原因应该是没有及时让hibernate把数据提交到数据库,等提交的时机到了时,却发现对象已经没法处理了。
for(Customer cstm:customers){
//do noting
}
也会报错,只要是访问到了Customer的PO就完蛋。我还测试了其他跟Course多对一关联的对象,Course是一端,可以正常运行,比如:
Set<Teacher> teachers = course.getTeachers();
for(Teacher tch:teachers){
//anyting..
}
这让我纳闷,Teacher类和Customer类的区别在于:
1.Customer类同时还用做Spring Security的UserDetail,但那个应该影响不到hibernate的session。
2.Customer拥有其他的集合对象,比如Customer.getRoles(),而Teacher类只有普通的字段。从这点看来很可疑,因为collection [] was not processed by flush中,[]内就是Customer.role或者Customer其他的集合对象。但是为什么会这样?现在我在怀疑openSessionInView机制对其造成的影响,在openSessionInView中,session生命周期比事务长,用户发起request,后台调用方法对Course对象update,PostUpdateEventListener立刻捕捉到了这一操作并执行上述代码,而这时session因为openSessionInView机制而尚未关闭,但是对Course进行update操作的方法的事务已经结束。
不知道这样会造成什么影响,如果是这个原因又如何规避。
https://forum.hibernate.org/viewtopic.php?f=1&t=1008222
重点这句
The error message indicates that something is happening during the flush that causes non-initialized lazy objects to be initialized.
是不是和customer关联的迟加载对象因为某些原因未被初始化的缘故org.hibernate.AssertionFailure: collection [???] was not processed by flush()
这句话的意思想必也是collection没有在flush方法中被处理,因此报错
谢谢,基本可以认为是懒加载的问题,OSIV机制中,一个线程始终使用一个session,而出发hibernate监听器时,原本是应该单独使用另一个session的,结果因为OSIV强制使用一个session而导致了一些不可控制的问题。最后我把Hibernate监听器里调用的方法以多线程方式触发,解决了这个问题。
一定要把取到的关联对象使用之后设为null,如果需要方法传递的话 最好传递一个ID过去 然后查询出来 然后设为null 就可以了
如果不设为null,关联的对象也会保留下来