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

Joh*_*eur 38 java spring hibernate transactional

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

的applicationContext

<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
Run Code Online (Sandbox Code Playgroud)

我的方法

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

我的问题是为什么MyObject被持久化到数据库?

mer*_*ike 57

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

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

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

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

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

  • 这是有道理的,但我怎么能分离我的实体.我正在使用JPA查询来获取实体,我需要为特定的只读操作操作子记录,以便我使用与请求匹配的JSON进行响应.但是,我不想删除或更新不适用于该请求的子记录; 只是从用户屏蔽它们. (2认同)

San*_*ndy 8

我曾经@Transactional(readOnly = true)解决过


Pio*_*cki 7

如果你正在使用JPA,那么规范说如果你的实体处于托管状态(这就是你通过在活动事务中从DAO获取数据而做的事情),那么对它做出的所有更改都将反映在事务提交期间的数据库.

所以,换句话说- 这并不重要,如果你调用更新操作或不是因为事务提交将刷新对数据库的更改.


小智 5

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

步骤一::

getSession().setFlushMode(FlushMode.MANUAL) // [FlushMode.NEVER is depracated in 4.x]
Run Code Online (Sandbox Code Playgroud)

第二步:

getSession().clear(); //This will actually discard all changes
Run Code Online (Sandbox Code Playgroud)