@Transactional
public MyEntity getEntity(long id) {
return dao.findOne(id);
//or select and update as well
}
Each time I call the transactional method: will I get any cached entity from hibernate (except for the first time)? Or will I always get the fresh entity fetched from DB?
This is important as I will have two independent apps that will share the same DB, and I want to ensure that hibernate does not return any cached entities while another app might have already updated the same entity in DB in the background.
At a high level, Spring creates proxies for all the classes annotated with @Transactional, either on the class or on any of the methods. The proxy allows the framework to inject transactional logic before and after the running method, mainly for starting and committing the transaction.
Hibernate deals with database specific transactions, whereas spring provides a general transaction management service. @Transactional is a nice way of configuring transaction management behaviour.
So when you annotate a method with @Transactional , Spring dynamically creates a proxy that implements the same interface(s) as the class you're annotating. And when clients make calls into your object, the calls are intercepted and the behaviors injected via the proxy mechanism.
@Transactional helps you to extend scope of Session . Session is open first time when getCurrentSession() is executed and it is closed when transaction ends and it is flushed before transaction commits. In Spring, If we use getCurrentSession() in non-transactional context we get an exception.
If this is the transaction boundary for your service layer then Hibernate will create a new Session, meaning there's nothing in the first level cache. If you try to call the findOne
method twice within the same service method, the second call will fetch the entity from the cache.
Successive service method calls (e.g. getEntity) always end up with a new Hibernate Session, so a fresh entity is loaded from the database.
If you employ a 2nd level cache and activate it for this entity, then Hibernate will always hit the cache first and fallback to database loading, on a cache miss.
To prevent data integrity anomalies, consider using optimistic locking anyway.
The short answer is yes.
The long answer is: all that @Transactional does is to provide a hibernate session for you, and begin/commit a transaction, if configured to do so.
It doesn't care whether the session has cache enabled or not. The caching is done internally by the session.
So all you need is to understand hibernate cache:
First level cache (per Session) is enabled by default and you can't disable it,
Second level cache (per SessionFactory) is disables by default, see here how to enable Ehcache (only @Cache annotated entities end up in the 2nd level cache).
Whether @Transactional will open new session, or will reuse existing one, is configurable, it depends on CurrentSessionContext implementation. You can plug your own implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With