1.Three code styles
Use hibernate's transaction:
session.beginTransaction();
// ... interact with database
session.getTransaction().commit();
Use JTA:
javax.transaction.UserTransaction tx = new InitialContext().lookup("javax.transaction.UserTransaction");
// ... use session to interact with database
tx.commit();
Use CMT:
// interact with database, don't need to write any code to manage transaction
2.TransactionManagerLookup
TransactionManagerLookup is used by JDBCContext to find JTA TransactionManager to register a CacheSynchronization. Also it's used by TransactionFactory to find JNDI name for UserTransaction.
Use "hibernate.transaction.manager_lookup_class" to config this class.
TransactionManagerLookup
|--- -> [TransactionManager ] -> JDBCContext
|
|--- -> [UserTransaction JNDI name] -> TransactionFactory
3.TransactionFactory
TransactionFactory is used to create hibernate transaction objects. There are 3 implementations, JDBC, JTA and CMT, though hibernate transaction seems only useful for JDBC, the JTA and CMT implementations allow client codes to shift from JDBC to JTA or CMT without change.
Use "hibernate.transaction.factory_class" to config this class, note that though it may seem ok when you use JDBCTransactionFactory in JTA or CMT environment, hibernate will do his best to dectect the correct transaction mode, it may still has some problem when you use Interceptor, the Transaction object passed to the Interceptor will be JDBCTransaction in JTA or CMT enviroment.
4.How hibernate detect the type of transaction to use automatically?
Hibernate will first try to find out whether a callback is registered and use TransactionManager to see if there's currently a transaction, if yes, it will register a synchronization, if no, it will rely on client code to use hibernate's transaction objects to manage transaction.
5.How hibernate implement auto flush and close after transaction?
If hibernate transaction is used, this is done by transaction object's commit method, if JTA or CMT is used, hibernate will register a CacheSynchronization to current transaction so that it can be notified before / after global transaction is commited.
6.Operations in sequence
Transaction calls and other operations may appear in any sequence, the order of which has sinificant impact on underlying process. Here's all the available operations: transaction begin / commit / rollback (transaction may be JDBCTransaction, JTATransaction, CMTTransaction, JTA UserTransaction or CMT declarative transaction, also, commit may trigger auto flush), open session, close session, explicit operations (like save, update, flush), lazy load.
6.1.Open session
For JTA and CMT, the openSession() method call can either be placed before or after transaction begin.
6.2.Close session
For JTA and CMT, the close() method call can either be placed before or after transaction commit. Note that when placed before transaction commit, though connection is closed, the related transaction branch will still in effect, so sqls emitted by this session can still be committed, but since the session is closed, when global transaction commits, the managedFlush() method (call by
CacheSynchronization) will not flush, this means that auto flush will be disable if session is closed before JTA or CMT transaction, so in this case, you must call flush() manually before closing the session.
6.3.Explicit operation and lazy load
These operations should appear within transaction boundary, but if they don't, for JDBC transaction, it's ok since session will always opens a new connection and set auto commit to be false before emitting any sql, this implies that a new transaction is started, for JTA or CMT transaction, the result will depend on drivers implementation, seems some will create a local transaction while others may throw an exception.
7.About first-level cache
Hibernate's first level cache is invalidated only when session is closed, this means that first-level cache can be used through several transaction. Also note that first-level cache may be used for dirty checking while flush (or auto flush during commit), this means that objects return by previous transaction can be check for dirty and has it's status sync with database in current transaction.
8.Questions?
What happen if user provided connection is used?
What if plain jdbc is expected to be used, but it's also inside JTA container?
Any impact for different connection release mode?