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

Java 事务性保存而不调用更新方法,java,hibernate,spring,transactional,Java,Hibernate,Spring,Transactional,我有一个用@Transactional注释的方法。我从Oracle数据库中检索一个对象,更改一个字段,然后从该方法返回。我忘了保存对象,但发现数据库还是会更新 应用程序上下文 <tx:annotation-driven /> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="

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

应用程序上下文

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

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

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


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

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

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

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

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

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


我发现阻止数据库的自动更新需要两个步骤

第一步:

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

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

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

对于JPA,请调用
entityManager.detach(entity)
以避免自动刷新。但是需要提醒您,分离的实体将在延迟抓取、级联更新等操作后丢失。

因为框架检测到对象的值发生了变化,并在不调用persist方法的情况下为您保存了它?我怎样才能预防它?我甚至抛出了一个异常,但它仍然存在?不,如果你抛出一个异常,它将不会持续。您可以控制它,您只需要阅读文档并学习如何使用framework.John。你是怎么解决的。我也有同样的问题谢谢,我搜索了又搜索,但我想我在某个地方遇到了配置问题。天啊,这很有道理,也很简单。@Piotr,只是想知道这是否是正确的编码实践?这很有道理,但我如何分离我的实体呢。我正在使用JPA查询来获取实体,我需要为特定的只读操作操作操作子记录,以便使用与请求匹配的JSON进行响应。但是,我不想删除或更新不适用于该请求的子记录;只需对用户屏蔽它们。@meriton,只是想知道这是否是正确的编码实践?@meriton完美的回答!
getSession().clear(); //This will actually discard all changes