我有一个用@Transactional注释的方法。我从Oracle数据库检索一个对象,更改一个字段,然后从该方法返回。我忘了保存对象,但是发现无论如何都会更新数据库。
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会持久保存到数据库?
因为hibernate将自动检测对 持久性 实体所做的更改并相应地更新数据库。hibernate参考手册的第11章中记录了此行为。相关部分为:
Hibernate定义并支持以下对象状态: 瞬态 -如果对象只是使用new运算符实例化的,则该对象是瞬态的,并且它与Hibernate Session无关。它在数据库中没有持久性表示形式,也没有分配标识符值。如果应用程序不再拥有引用,则瞬态实例将被垃圾收集器破坏。使用Hibernate会话使对象持久化(并让Hibernate处理此转换需要执行的SQL语句)。 持久 -持久实例在数据库中具有表示形式和标识符值。它可能只是被保存或加载,但是根据定义,它在Session范围内。当工作单元完成时,Hibernate将检测对处于持久状态的对象所做的任何更改,并将该状态与数据库同步。当应将对象设置为瞬态时,开发人员不会执行手动的UPDATE语句或DELETE语句。 已分离 -分离的实例是已持久的对象,但其会话已关闭。当然,对对象的引用仍然有效,并且分离的实例甚至可以在此状态下进行修改。分离的实例可以在稍后的时间点重新附加到新的Session,使其(以及所有修改)再次持久。此功能为需要用户思考时间的长时间运行的工作单元启用了编程模型。我们称它们为应用程序交易,即从用户角度来看的一个工作单元。
Hibernate定义并支持以下对象状态:
瞬态 -如果对象只是使用new运算符实例化的,则该对象是瞬态的,并且它与Hibernate Session无关。它在数据库中没有持久性表示形式,也没有分配标识符值。如果应用程序不再拥有引用,则瞬态实例将被垃圾收集器破坏。使用Hibernate会话使对象持久化(并让Hibernate处理此转换需要执行的SQL语句)。
持久 -持久实例在数据库中具有表示形式和标识符值。它可能只是被保存或加载,但是根据定义,它在Session范围内。当工作单元完成时,Hibernate将检测对处于持久状态的对象所做的任何更改,并将该状态与数据库同步。当应将对象设置为瞬态时,开发人员不会执行手动的UPDATE语句或DELETE语句。
已分离 -分离的实例是已持久的对象,但其会话已关闭。当然,对对象的引用仍然有效,并且分离的实例甚至可以在此状态下进行修改。分离的实例可以在稍后的时间点重新附加到新的Session,使其(以及所有修改)再次持久。此功能为需要用户思考时间的长时间运行的工作单元启用了编程模型。我们称它们为应用程序交易,即从用户角度来看的一个工作单元。