今天在spring+hibernate的整合中使用了hibernate的 二级缓存与事务管理 时频频报错。
[org.hibernate.cache.internal.CollectionCacheInvalidator.evictCache(CollectionCacheInvalidator.java:134)]
org.hibernate.TransientObjectException: The instance was not associated with this session
at org.hibernate.internal.SessionImpl.getIdentifier(SessionImpl.java:1488)
at org.hibernate.cache.internal.CollectionCacheInvalidator.evictCache(CollectionCacheInvalidator.java:111)
at org.hibernate.cache.internal.CollectionCacheInvalidator.onPostUpdate(CollectionCacheInvalidator.java:71)
at org.hibernate.action.internal.EntityUpdateAction.postUpdate(EntityUpdateAction.java:264)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:211)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:447)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:333)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:335)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1224)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:464)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2894)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2270)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:146)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:230)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
at org.springframework.orm.hibernate5.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:581)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:485)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy369.upUser(Unknown Source)
其实,我是想在使用spring的事务管理的情况下,看看hibernate配置了@cache是否会生效,初始结果session对于查询操作没有问题,但当测试修改update时就报错。
这时我就在想,是不是@cache没有设置为可读写,即@Cache(usage=CacheConcurrencyStrategy.READ_WRITE ),发现我明明已经设置了(发现BUG时往往就是这种情况)。接着又怀疑是spring的@transactional配置的问题,百度,发现不是这问题。思路又转到cache的问题上,会不会是ehcache的配置问题?继续百度,重新学习ehcache的配置,发现还不是这个问题。
那问题就真的来了,冷静加爆粗的我只得DEBUG,我首先去掉spring的@transaction,改用hibernate的
session.beginTransaction();
session.update(u);
session.getTransaction().commit();
继续报错,说明不是spring的@transactional问题。接着关闭hibernate的缓存,
发现不报错了!!!重头戏来了,既然是二级缓存的问题,那么我就一条条配置重新加入,
终于问题的关键找到了:
<property name="hibernate.cache.auto_evict_collection_cache">true</property>
原来是你。。。怎么会??这个可是我看完文档后亲自加入的(自作自受),呵呵,无论如何也得有个说法吧,我又看看了文档,发现自己理解不透,百度,居然没有人出现这个问题!!(可能是我没搜到),只得Google,
原来国外已有人碰到该问题,报错的原因来自hibernate的bug,这个从hibernate4.x时就有了,修复到5.1还是存在,我醉了。虽然开发的人修复很多次,但感觉还是不稳定,建议还是不要使用!! 附上该问题的网址:https://hibernate.atlassian.net/browse/HHH-10614