<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sf" />
</property>
</bean>
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还有已经开启的事务。