I have the following service:
@Service
public class CamelService {
@Transactional
public aCamelThing() {
Camel camel = this.camelRepository.findOne(1);
System.out.println(camel.getCamelName()); // prints "normalCamel"
// simple hql set field 'camelName'
int res = this.camelRepository.updateCamelName(1,"superCamel!");
Camel camelWithNewName = this.camelRepository.findOne(1);
System.out.println(camelWithNewName .getCamelName()); // prints "normalCamel" ?!?!?
}
}
Any idea how can i achieve the goal that the second println will print: "superCamel!" ? (separating the second call to a new transaction is not ideal).
The reason you see this working as it works is quite simple: JPA is defined to work that way.
I am assuming you trigger an update query for
updateCamelName(…)
. The JPA specification states the following for update and delete operations:This means, that if you need to see the changes of such an operation you need to do the following things:
EntityManager
after this operation. Spring Data JPA's@Modifying
annotation has aclearAutomatically
flag defaulting tofalse
. If that is set to true, invoking the query method will clear theEntityManager
automatically (as the name suggests. Use that with caution, as it will effectively drop all pending changes that have not been flushed to the database yet!EntityManager
. CallingfindOne(…)
on the repository seems like a reasonable way to do this as this roughly translates intoEntityManager.find(…)
. Be aware that this might still hit 2nd level caches configured on the persistence provider.The safest way to work around this is - as the spec suggests - to use update queries only for bulk operations and fall back to the "load entity, alter, merge" approach by default.