Hibernate结合Spring,Spring提供了org.springframework.orm.hibernate3.HibernateTransactionManager来管理Hibernate事务
下面是HibernateTransactionManager类部分源码的解析:
public class HibernateTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, BeanFactoryAware, InitializingBean { private SessionFactory sessionFactory; private DataSource dataSource; private boolean autodetectDataSource = true; private boolean prepareConnection = true; private boolean hibernateManagedSession = false; private boolean earlyFlushBeforeCommit = false; private Object entityInterceptor; private SQLExceptionTranslator jdbcExceptionTranslator; private SQLExceptionTranslator defaultJdbcExceptionTranslator; protected Object doGetTransaction() { HibernateTransactionObject txObject = new HibernateTransactionObject(); txObject.setSavepointAllowed(isNestedTransactionAllowed()); SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory()); if (sessionHolder != null) { if (logger.isDebugEnabled()) { logger.debug("Found thread-bound Session [" + SessionFactoryUtils.toString(sessionHolder.getSession()) + "] for Hibernate transaction"); } txObject.setSessionHolder(sessionHolder); } else if (this.hibernateManagedSession) { try { Session session = getSessionFactory().getCurrentSession(); if (logger.isDebugEnabled()) { logger.debug("Found Hibernate-managed Session [" + SessionFactoryUtils.toString(session) + "] for Spring-managed transaction"); } txObject.setExistingSession(session); } catch (HibernateException ex) { throw new DataAccessResourceFailureException( "Could not obtain Hibernate-managed Session for Spring-managed transaction", ex); } } if (getDataSource() != null) { ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(getDataSource()); txObject.setConnectionHolder(conHolder); } return txObject; } protected void doBegin(Object transaction, TransactionDefinition definition) {//transaction是HibernateTransactionObject,definition配置信息的描述 HibernateTransactionObject txObject = (HibernateTransactionObject) transaction; if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) { throw new IllegalTransactionStateException( "Pre-bound JDBC Connection found! HibernateTransactionManager does not support " + "running within DataSourceTransactionManager if told to manage the DataSource itself. " + "It is recommended to use a single HibernateTransactionManager for all transactions " + "on a single DataSource, no matter whether Hibernate or JDBC access."); } Session session = null; try { if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {//getSessionHolder()==null或者不是同步的就open一个Session并填充到SessionHolder同步 Interceptor entityInterceptor = getEntityInterceptor(); Session newSession = (entityInterceptor != null ? getSessionFactory().openSession(entityInterceptor) : getSessionFactory().openSession()); if (logger.isDebugEnabled()) { logger.debug("Opened new Session [" + SessionFactoryUtils.toString(newSession) + "] for Hibernate transaction"); } txObject.setSession(newSession); } session = txObject.getSessionHolder().getSession();//获得上一步填充好的同步Session if (this.prepareConnection && isSameConnectionForEntireSession(session)) { // We're allowed to change the transaction settings of the JDBC Connection. if (logger.isDebugEnabled()) { logger.debug( "Preparing JDBC Connection of Hibernate Session [" + SessionFactoryUtils.toString(session) + "]"); } Connection con = session.connection(); Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); } else { // Not allowed to change the transaction settings of the JDBC Connection. if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { // We should set a specific isolation level but are not allowed to... throw new InvalidIsolationLevelException( "HibernateTransactionManager is not allowed to support custom isolation levels: " + "make sure that its 'prepareConnection' flag is on (the default) and that the " + "Hibernate connection release mode is set to 'on_close' (SpringTransactionFactory's default). " + "Make sure that your LocalSessionFactoryBean actually uses SpringTransactionFactory: Your " + "Hibernate properties should *not* include a 'hibernate.transaction.factory_class' property!"); } if (logger.isDebugEnabled()) { logger.debug( "Not preparing JDBC Connection of Hibernate Session [" + SessionFactoryUtils.toString(session) + "]"); } } if (definition.isReadOnly() && txObject.isNewSession()) { // Just set to NEVER in case of a new Session for this transaction. session.setFlushMode(FlushMode.NEVER); } if (!definition.isReadOnly() && !txObject.isNewSession()) { // We need AUTO or COMMIT for a non-read-only transaction. FlushMode flushMode = session.getFlushMode(); if (flushMode.lessThan(FlushMode.COMMIT)) { //比较刷新数据库优先级,如果是COMMIT就设置为AUTO session.setFlushMode(FlushMode.AUTO); txObject.getSessionHolder().setPreviousFlushMode(flushMode); } } Transaction hibTx = null; //Hibernate事务 // Register transaction timeout. int timeout = determineTimeout(definition); //超时时间 if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { //!=-1说明没有超时 // Use Hibernate's own transaction timeout mechanism on Hibernate 3.1 // Applies to all statements, also to inserts, updates and deletes! hibTx = session.getTransaction(); hibTx.setTimeout(timeout); hibTx.begin(); } else { // Open a plain Hibernate transaction without specified timeout. hibTx = session.beginTransaction(); } // Add the Hibernate transaction to the session holder. txObject.getSessionHolder().setTransaction(hibTx);//该事务是活动的 // Register the Hibernate Session's JDBC Connection for the DataSource, if set. if (getDataSource() != null) { //对DataSource线程绑定 Connection con = session.connection(); ConnectionHolder conHolder = new ConnectionHolder(con); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { conHolder.setTimeoutInSeconds(timeout); } if (logger.isDebugEnabled()) { logger.debug("Exposing Hibernate transaction as JDBC transaction [" + con + "]"); } TransactionSynchronizationManager.bindResource(getDataSource(), conHolder); txObject.setConnectionHolder(conHolder); } // Bind the session holder to the thread. if (txObject.isNewSessionHolder()) { //isNewSessionHolder()保存的是该SessionHolder是否是同步的,如果不是说明是一个新的SessionHolder,所以要重新绑定到当前线程中。 TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder()); } txObject.getSessionHolder().setSynchronizedWithTransaction(true); //最后标识事务已经同步 } catch (Exception ex) { if (txObject.isNewSession()) { try { if (session.getTransaction().isActive()) { session.getTransaction().rollback(); } } catch (Throwable ex2) { logger.debug("Could not rollback Session after failed transaction begin", ex); } finally { SessionFactoryUtils.closeSession(session); } } throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex); } } protected Object doSuspend(Object transaction) { //暂停事务,将所有绑定在线程上的资源解绑 HibernateTransactionObject txObject = (HibernateTransactionObject) transaction; txObject.setSessionHolder(null); SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(getSessionFactory()); txObject.setConnectionHolder(null); ConnectionHolder connectionHolder = null; if (getDataSource() != null) { connectionHolder = (ConnectionHolder) TransactionSynchronizationManager.unbindResource(getDataSource()); } return new SuspendedResourcesHolder(sessionHolder, connectionHolder); } protected void doResume(Object transaction, Object suspendedResources) { //恢复事务,重新sessionfactory和datasource绑定到线程上 SuspendedResourcesHolder resourcesHolder = (SuspendedResourcesHolder) suspendedResources; if (TransactionSynchronizationManager.hasResource(getSessionFactory())) { // From non-transactional code running in active transaction synchronization // -> can be safely removed, will be closed on transaction completion. TransactionSynchronizationManager.unbindResource(getSessionFactory()); //为了保险绑定之前先对sessionfactory解绑 } TransactionSynchronizationManager.bindResource(getSessionFactory(), resourcesHolder.getSessionHolder()); if (getDataSource() != null) { TransactionSynchronizationManager.bindResource(getDataSource(), resourcesHolder.getConnectionHolder()); } } }①doGetTransaction()
1、如果使用了OpenSessionInViewFilter则获得已经绑定了当前线程的SessionHolder(以SessionFactory为key,Session为value绑定在当前线程中,至于如何绑定的看OpenSessionInViewFilter线程绑定session),如果是Hibernate事务管理则直接获得当前Session。
2、org.springframework.orm.hibernate3.SessionHolder:对Session的包装,并对保存了Session的Map做同步
public class SessionHolder extends ResourceHolderSupport { private static final Object DEFAULT_KEY = new Object();
private final Map sessionMap = Collections.synchronizedMap(new HashMap(1));
private Transaction transaction;
private FlushMode previousFlushMode;
public SessionHolder(Session session) { addSession(session); }
public void addSession(Session session) { addSession(DEFAULT_KEY, session); } public void addSession(Object key, Session session) { Assert.notNull(key, "Key must not be null"); Assert.notNull(session, "Session must not be null"); this.sessionMap.put(key, session); }
}
3、ConnectionHolder:对Connection一些信息的包装
public class ConnectionHolder extends ResourceHolderSupport { public static final String SAVEPOINT_NAME_PREFIX = "SAVEPOINT_"; private ConnectionHandle connectionHandle; private Connection currentConnection; private boolean transactionActive = false; private Boolean savepointsSupported; private int savepointCounter = 0; /** * Create a new ConnectionHolder for the given ConnectionHandle. * @param connectionHandle the ConnectionHandle to hold */ public ConnectionHolder(ConnectionHandle connectionHandle) { Assert.notNull(connectionHandle, "ConnectionHandle must not be null"); this.connectionHandle = connectionHandle; } /** * Create a new ConnectionHolder for the given JDBC Connection, * wrapping it with a {@link SimpleConnectionHandle}, * assuming that there is no ongoing transaction. * @param connection the JDBC Connection to hold * @see SimpleConnectionHandle * @see #ConnectionHolder(java.sql.Connection, boolean) */ public ConnectionHolder(Connection connection) { this.connectionHandle = new SimpleConnectionHandle(connection); } /** * Create a new ConnectionHolder for the given JDBC Connection, * wrapping it with a {@link SimpleConnectionHandle}. * @param connection the JDBC Connection to hold * @param transactionActive whether the given Connection is involved * in an ongoing transaction * @see SimpleConnectionHandle */ public ConnectionHolder(Connection connection, boolean transactionActive) { this(connection); this.transactionActive = transactionActive; }
}
②doBegin(Object transaction, TransactionDefinition definition):
1、txObject.setSession(newSession):
HibernateTransactionObject:
public void setSession(Session session) { this.sessionHolder = new SessionHolder(session); this.newSessionHolder = true; this.newSession = true;}
SessionHolder:
private final Map sessionMap = Collections.synchronizedMap(new HashMap(1));
public SessionHolder(Session session) { addSession(session);}
public void addSession(Session session) { addSession(DEFAULT_KEY, session);}
public void addSession(Object key, Session session) { Assert.notNull(key, "Key must not be null"); Assert.notNull(session, "Session must not be null"); this.sessionMap.put(key, session);}
最终将Session添加到了一个同步HashMap中
2、doBegin完成后当前线程中就 会有一个以ThreadLocal<Map>为key ,Map为value的ThreadLocal.ThreadLocalMap,并且ThreadLocal.ThreadLocalMap的value里又会有两对值,一个是以SessionFactory为key,session为value;一个是以DataSource为key,Connection为value;HibernateTransactionObjecttxObject = (HibernateTransactionObject) transaction;txObject则保存着绑定在同一线程中的session、connection还有已经开启的事务。