事务性保存而不调用更新方法
Posted
技术标签:
【中文标题】事务性保存而不调用更新方法【英文标题】:Transactional saves without calling update method 【发布时间】:2012-01-01 17:15:30 【问题描述】:我有一个用@Transactional 注释的方法。我从我的 Oracle DB 中检索一个对象,更改一个字段,然后从该方法返回。我忘了保存对象,但发现数据库无论如何都会更新。
应用程序上下文
<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 会被持久化到数据库中?
【问题讨论】:
因为框架检测到对象的值发生了变化并为你保存了 不调用persist方法?我该如何预防?我什至抛出了一个异常,它仍然存在? 不,如果您抛出异常,它将不会持续存在。而且你可以控制它,你只需要阅读文档并学习如何使用框架。 约翰。你是如何解决这个问题的。我也有同样的问题 【参考方案1】:对于 JPA,请致电 entityManager.detach(entity)
以避免自动刷新。但是您需要注意,分离的实体在之后会失去 ORM 魔法,例如延迟抓取,级联更新。
【讨论】:
【参考方案2】:我用@Transactional(readOnly = true)
解决了
【讨论】:
@Transactional(propagation = Propagation.REQUIRED, readOnly = true) 为我工作【参考方案3】:我发现阻止自动更新数据库是一个两步过程。
第一步::
getSession().setFlushMode(FlushMode.MANUAL) // [FlushMode.NEVER is depracated in 4.x]
第二步:
getSession().clear(); //This will actually discard all changes
【讨论】:
【参考方案4】:因为休眠会自动检测对持久实体所做的更改并相应地更新数据库。这种行为记录在休眠参考手册的chapter 11 中。相关部分内容如下:
Hibernate 定义并支持以下对象状态:
Transient - 如果一个对象刚刚使用 new 运算符实例化,并且它与 Hibernate Session 无关,则它是瞬态的。它在数据库中没有持久表示,也没有分配标识符值。如果应用程序不再持有引用,垃圾收集器将销毁瞬态实例。使用 Hibernate Session 使对象持久化(并让 Hibernate 处理此转换需要执行的 SQL 语句)。
持久化 - 持久化实例在数据库中具有表示形式和标识符值。它可能刚刚被保存或加载,但是,根据定义,它在 Session 的范围内。 Hibernate 将检测对处于持久状态的对象所做的任何更改,并在工作单元完成时将状态与数据库同步。开发人员不执行手动 UPDATE 语句,或在对象应为瞬态时执行 DELETE 语句。
已分离 - 已分离实例是一个已持久化的对象,但其 Session 已关闭。当然,对对象的引用仍然有效,分离的实例甚至可能在这种状态下被修改。一个分离的实例可以在稍后的时间点重新附加到一个新的 Session 上,使其(以及所有修改)再次持久化。此功能为需要用户思考时间的长时间运行的工作单元启用了编程模型。我们称它们为应用事务,即从用户的角度来看的一个工作单元。
【讨论】:
这是有道理的,但我怎样才能分离我的实体。我正在使用 JPA 查询来获取实体,并且我需要为特定的只读操作操作子记录,以便使用与请求匹配的 JSON 进行响应。但是我不想删除或更新不适用于该请求的子记录;只是对用户屏蔽它们。 @meriton, , 只是想知道这是否是正确的编码实践? @meriton 完美回答!【参考方案5】:如果您使用的是 JPA,那么规范说明如果您的实体处于托管状态(这就是您通过在活动事务中从 DAO 获取数据来执行的操作),在事务提交期间,对其所做的所有更改都会反映在数据库中。
因此,换句话说 - 是否调用更新操作并不重要,因为事务提交会将更改刷新到数据库。
【讨论】:
谢谢,我找了又找,但以为我在某个地方有配置问题。天哪,这说得通,而且很简单。 @Piotr, , 只是想知道这是否是正确的编码实践?以上是关于事务性保存而不调用更新方法的主要内容,如果未能解决你的问题,请参考以下文章
save()saveOrUpdate()merge()的区别