Search code examples
javaspringhibernatetransactional

Spring @Transactional(readOnly=true) revert the properties?


Just a simple Question with a Car-entity persisted field color of value red:

00  @Transactional public class MyBean{...
01    public void test(){
02        Car c = s.find(Car.class,1);
03        c.setColor("blue");
04        test1(c);
05        System.out.println(c.getColor());   
06    }
07    @Transactional(readOnly=true)
08    public void test1(Car c){
09        c.setName("black");
10    }
11  }

Assuming, we are in Spring ORM TX-Transactional-Annotation environment, with transactional semantics and transaction scoped persistence context.

What will be printed to Console?

  • red
  • blue
  • black

Solution

  • Assuming transactional semantics are enabled when calling methods of the same instance and NESTED transaction propagation: It depends on the scope of the persistence context.

    Assuming a transaction scoped persistence context: black is printed to the console. The car instance is detached, because it was fetched outside the readonly transaction and is not merged into the readonly transaction. Calling the setter on a detached instance is safe (like the call to setColor("blue").

    Assuming an extended scope of the persistence context: black is also printed. From the javadoc of @Transactional

    If

    A transaction manager which cannot interpret the read-only hint will not throw an exception when asked for a read-only transaction.

    And from the JPA 2.0 Spec Section 2.4.1.2 Mapping of Derived Identities:

    The embedded id attributes that correspond to the relationship are treated by the provider as “read only”—that is, any updates to them on the part of the application are not propagated to the database.

    But I'm not 100% sure, if there isn't an exception thrown. Since the color property isn't an embedded id the behaviour may vary.

    If transactional semantics are available via proxies then see the answer of Adrian Shum