【问题标题】:Hibernate: Prevent update of dirty instances that were never update()'ed manually in the session休眠:防止更新从未在会话中手动更新()的脏实例
【发布时间】:2011-06-24 09:32:00
【问题描述】:

我遇到了 Hibernate 的一种行为,我不知道它是我的代码中的一个特性还是 hibernate 的错误/错误用法。

我的会话的 FlushMode 设置为 FlushMode.AUTO。如果我执行一个选择查询,休眠自动刷新过程会跳入并尝试更新一个实体,因为它认为它很脏。但是,我没有在会话中的某个地方为这个实体调用 update(),我什至认为我没有修改它,甚至不是因为级联。 结果是自动更新的脏实体导致我的数据库处于不需要的状态。我正在使用 SaveUpdate 实体侦听器跟踪此不需要的实体更新。

我正在从堆栈跟踪中收集所有这些信息(我给你看一段摘录,我的上述理论可能是错误的;))

2011-06-24 09:51:07,790 28671957 (SaveUpdateEventListener.java:140) FATAL  - Stacktrace from last unwanted update
java.lang.Exception
    at a.b.dao.listener.SaveUpdateEventListener.checkEntity(SaveUpdateEventListener.java:138)
    at a.b.dao.listener.SaveUpdateEventListener.onSaveOrUpdate(SaveUpdateEventListener.java:38)
    at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535)
    at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527)
    at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:241)
    at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:292)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:240)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:193)
    at org.hibernate.engine.Cascade.cascade(Cascade.java:154)
    at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:154)
    at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:145)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88)
    at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:58)
    at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:997)
    at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1142)
    at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
    at org.springframework.orm.hibernate3.HibernateTemplate$30.doInHibernate(HibernateTemplate.java:921)
    at org.springframework.orm.hibernate3.HibernateTemplate$30.doInHibernate(HibernateTemplate.java:1)
    at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
    at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
    at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:912)
    >> at a.b.dao.pricing.PricingDao.list(PricingDao.java:36) << THE SELECT STATEMENT
    at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
    at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:688)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:621)
    ...

那么,脏字段的自动更新是一项功能吗?如果是,是由 FlushMode.AUTO 引起的吗?我可以使用 FlushMode.MANUAL 禁用此功能吗?

【问题讨论】:

    标签: java hibernate spring jakarta-ee


    【解决方案1】:

    您必须对有问题的对象执行某些操作,使 Hibernate 认为它们是脏的。与其尝试破坏正常的 Hibernate 行为,不如尝试在您的代码中找出 Hibernate 的错误/误用。

    或者,如果您绝对不需要 Hibernate 会话的智能来检测脏对象并基于此发出插入、更新和删除,请考虑使用 Hibernate 无状态会话。

    【讨论】:

    • 有没有办法查看哪个属性被标记为脏?我已经查看了脏拦截器,但我想我仍然需要知道 Hibernate 如何比较属性
    • 你最好的办法是在一个非常有限的会话中重现这个问题,只有少数对象在 Hibernate 会话缓存中,并逐步执行代码。你可能想看看这篇文章:blog.xebia.com/2009/04/why-did-hibernate-update-my-database
    • 这可能是一种方法。问题是这个环境是一个高负载的服务器,并且有多个线程在运行:/
    • @Erik:如果您正在为此类部署进行开发,那么您不能没有单元测试。如果您可以在单元测试中重现此行为,您甚至可以在不接触生产服务器的情况下单步执行相同的 Hibernate 代码。
    • 启用 Hibernate 类别 org.hibernate=TRACE 的日志记录,将准确显示哪些属性是脏的(这就是我检测它们的方式)。
    猜你喜欢
    • 2020-02-16
    • 2017-11-19
    • 1970-01-01
    • 1970-01-01
    • 2019-03-26
    • 1970-01-01
    • 2016-09-02
    • 2012-12-16
    • 2013-10-19
    相关资源
    最近更新 更多