Search code examples
springjpatransactional

Why does @Transactional save automatically to database


I have a method annotated with @Transactional. I retrieve an object from my DB, change a field, and then return from the method. Without saving my object, the database gets updated anyway which is strange.

Could you please tell me how to avoid this beahvior?


Solution

  • This behaviour is one of the main purposes of transactionality.

    Before the transactional method is about to return, the transaction commits, meaning all changes to the managed entities are flushed to the database.

    If an error occurs, the transaction will be rolled back, meaning that no changes will be committed to the database.

    You are probably getting the LazyInitializationException when trying to access a lazily loaded property, probably a collection from an entity. Lazily loded properties do not get instantiated when you fetch an entitiy from DB.

    If you access a lazily loaded property in a transaction, the persistence provider will create a query, instantiate the result and attach it to the 'parent' entity.

    EDIT: If you want to have the lazy properties loaded AND be able to change your entity without the changes being persisted to the DB, you can fetch the entity with fetch joins for the lazy properties.

    em.createQuery("SELECT e FROM MyEntity e JOIN FETCH e.lazyProp");
    

    Then proceed with one of the methods described by @orid.

    If you are not using fetch joins, you will need to access the lazily loaded properties while still inside the transaction:

    myEntity.getLazyProp().size();
    

    Note the call to size(). Calling the getter is not enough as you will get a proxy. You need to perform an operation that needs the actual data from the property.