Reputation: 435
I've got a Spring Data JPA Repository with a method like this:
//@QueryHints({ @QueryHint(name = "org.hibernate.readOnly", value = "true") })
@Transactional(readOnly = true)
Account findByUsername(String username);
When Account
is dirty, hibernate tries to flush it when invoking this method - which I don't want. I thought setting it to @Transactional(readOnly = true)
could help with this, but it doesn't. Interestingly using @QueryHints
with the concrete hibernate hint does work. Now I'm wondering why. Shouldn't @Transactional(readOnly=true)
have the same effect?
Upvotes: 6
Views: 5969
Reputation: 26552
If we want to stick to non-vendor specific ways you then i would try:
Option 1
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
Account findByUsername(String username);
Here we do run the query outside of any transaction, thus not affecting the existing state of persistence context. Think well if this case is suitable for this configuration.
Option 2
I assume you are doing some other modifications in the current transaction before you query for the user. I would suggest then setting the flush mode to commit on you query (or entity manager):
EntityManager em;
Account findByUsername(String username){
em.setFlushMode(FlushModeType.COMMIT);
// perform the query
}
OR
EntityManager em;
Account findByUsername(String username){
Query query = em.createQuery(..);
query.setFlushMode(FlushModeType.COMMIT);
// perform the query
}
The COMMIT flush mode tells the persistence provider that queries do not overlap with changed data in the persistence context, so it does not need to do anything in order to get the correct results.
Setting the flush mode on the query itself is an advisable approach.
Update: Option 3
As the last resort you can set that on the core configuration itself:
<property name="org.hibernate.flushMode" value="COMMIT"/>
Now this is to use when you cannot access the entity manager and set the flush mode manually.
Upvotes: 2