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

2022-08-31 15:22:41

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

应用语境

<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会持久化到数据库中?


答案 1

因为休眠将自动检测对持久性实体所做的更改,并相应地更新数据库。此行为记录在休眠参考手册的第 11 章中。相关部分内容如下:

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

  • 瞬态 - 如果对象刚刚使用 new 运算符实例化,并且未与休眠会话关联,则该对象为瞬态。它在数据库中没有持久表示形式,也没有分配标识符值。如果应用程序不再保存引用,则垃圾回收器将销毁瞬态实例。使用休眠会话使对象持久化(并让休眠处理需要为此转换执行的 SQL 语句)。

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

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


答案 2

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

因此,换句话说 - 是否调用更新操作并不重要,因为事务提交会将更改刷新到数据库。


推荐