Transactional saves without calling update method

帅比萌擦擦* 提交于 2019-11-26 09:28:46

问题


I have a method annotated with @Transactional. I retrieve an object from my Oracle DB, change a field, and then return from the method. I forgot to save the object, but discovered that the database gets updated anyway.

applicationContext

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

my method

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

my question is why does MyObject get persisted to the database?


回答1:


Because hibernate will automatically detect changes made to persistent entities and update the database accordingly. This behaviour is documented in chapter 11 of the hibernate reference manual. The relevant part reads:

Hibernate defines and supports the following object states:

  • Transient - an object is transient if it has just been instantiated using the new operator, and it is not associated with a Hibernate Session. It has no persistent representation in the database and no identifier value has been assigned. Transient instances will be destroyed by the garbage collector if the application does not hold a reference anymore. Use the Hibernate Session to make an object persistent (and let Hibernate take care of the SQL statements that need to be executed for this transition).

  • Persistent - a persistent instance has a representation in the database and an identifier value. It might just have been saved or loaded, however, it is by definition in the scope of a Session. Hibernate will detect any changes made to an object in persistent state and synchronize the state with the database when the unit of work completes. Developers do not execute manual UPDATE statements, or DELETE statements when an object should be made transient.

  • Detached - a detached instance is an object that has been persistent, but its Session has been closed. The reference to the object is still valid, of course, and the detached instance might even be modified in this state. A detached instance can be reattached to a new Session at a later point in time, making it (and all the modifications) persistent again. This feature enables a programming model for long running units of work that require user think-time. We call them application transactions, i.e., a unit of work from the point of view of the user.




回答2:


If you're using a JPA, than the specification says that if your Entity is in managed state (and this is what you do by fetching the data from the DAO within an active transaction), all changed made to it will be reflected in the database during the transaction commit.

So, in other words - it doesn't really matter if you invoke update operation or not because the transaction commit will flush the changes to the database.




回答3:


I found preventing automatic updates to the database is a two step process.

Step I: :

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

Step II :

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



回答4:


I used @Transactional(readOnly = true) to resolve it




回答5:


For JPA, call entityManager.detach(entity) to avoid auto flush. But you need be to aware the detached entity will lost ORM magic after, e.g. lazy fetching, cascade update.



来源:https://stackoverflow.com/questions/8190926/transactional-saves-without-calling-update-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!