事务性保存而不调用更新方法

时间:2011-11-19 00:42:12

标签: java hibernate spring transactional

我有一个用@Transactional注释的方法。我从Oracle DB中检索一个对象,更改一个字段,然后从该方法返回。我忘了保存对象,但发现无论如何都要更新数据库。

的applicationContext

<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

我的方法

@Transactional
public void myMethod(long id) {
    MyObject myObj = dao.getMstAttributeById(id);
    myObj.setName("new name");
    //dao.update(myObj);
}

我的问题是为什么MyObject会持久存储到数据库中?

5 个答案:

答案 0 :(得分:56)

因为hibernate会自动检测对 persistent 实体所做的更改并相应地更新数据库。这种行为记录在hibernate参考手册的chapter 11中。相关部分如下:

  

Hibernate定义并支持以下对象状态:

     
      
  • Transient - 如果一个对象刚刚使用new运算符进行实例化,并且它与Hibernate会话无关,则该对象是瞬态的。它在数据库中没有持久表示,并且没有分配标识符值。如果应用程序不再持有引用,则垃圾收集器将销毁瞬态实例。使用Hibernate Session使对象持久化(让Hibernate处理需要为此转换执行的SQL语句)。

  •   
  • 持久性 - 持久性实例在数据库中具有表示形式和标识符值。它可能刚刚被保存或加载,但是,它定义在Session的范围内。 Hibernate将检测对处于持久状态的对象所做的任何更改,并在工作单元完成时将状态与数据库同步。当对象应该是瞬态的时,开发人员不会执行手动UPDATE语句或DELETE语句。

  •   
  • 分离 - 分离的实例是一个持久的对象,但其会话已关闭。当然,对对象的引用仍然有效,甚至可以在此状态下修改分离的实例。可以在稍后的时间点将分离的实例重新附加到新的会话,使其(以及所有修改)再次持久化。此功能为需要用户思考的长时间运行工作单元启用编程模型。我们称之为应用程序事务,即从用户的角度来看工作单元。

  •   

答案 1 :(得分:5)

如果您使用的是JPA,那么如果您的实体处于托管状态,那么规范就会说明(这就是您通过在活动事务中从DAO获取数据而执行的操作),在事务提交期间,所有对其进行的更改都将反映在数据库中。

因此,换句话说 - 如果你调用更新操作,它并不重要因为事务提交会刷新对数据库的更改。

答案 2 :(得分:1)

我发现阻止对数据库的自动更新是一个两步过程。

第一步::

getSession().setFlushMode(FlushMode.MANUAL) // [FlushMode.NEVER is depracated in 4.x]

第二步:

getSession().clear(); //This will actually discard all changes

答案 3 :(得分:0)

我用@Transactional(readOnly = true)来解决

答案 4 :(得分:0)

对于JPA,请致电entityManager.detach(entity)以避免自动刷新。但是您需要知道,分离的实体在例如延迟抓取,级联更新。