1. 程式人生 > >hibernate 的 openSession 和 getCurrentSession 的實現

hibernate 的 openSession 和 getCurrentSession 的實現

openSession  :

public org.hibernate.classic.Session openSession() throws HibernateException {
return openSession(interceptor);
}


public org.hibernate.classic.Session openSession(Interceptor sessionLocalInterceptor)
throws HibernateException {
// note that this timestamp is not correct if the connection provider

// returns an older JDBC connection that was associated with a
// transaction that was already begun before openSession() was called
// (don't know any possible solution to this!)
long timestamp = settings.getCacheProvider().nextTimestamp();
return openSession( null, true, timestamp, sessionLocalInterceptor );
}




private SessionImpl openSession(
Connection connection,
   boolean autoClose,
   long timestamp,
   Interceptor sessionLocalInterceptor
) {
return new SessionImpl(
       connection,
       this,
       autoClose,
       timestamp,
       sessionLocalInterceptor == null ? interceptor : sessionLocalInterceptor,
       settings.getDefaultEntityMode(),
       settings.isFlushBeforeCompletionEnabled(),
       settings.isAutoCloseSessionEnabled(),
       settings.getConnectionReleaseMode()
);
}





private SessionImpl openSession(
Connection connection,
   boolean autoClose,
   long timestamp,
   Interceptor sessionLocalInterceptor
) {
return new SessionImpl(
       connection,
       this,
       autoClose,
       timestamp,
       sessionLocalInterceptor == null ? interceptor : sessionLocalInterceptor,
       settings.getDefaultEntityMode(),
       settings.isFlushBeforeCompletionEnabled(),
       settings.isAutoCloseSessionEnabled(),
       settings.getConnectionReleaseMode()
);
}






if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor().openSession();
}


public interface StatisticsImplementor {
public void openSession();


單例模式: 控制同步
private long sessionOpenCount;
public synchronized void openSession() {
sessionOpenCount++;
}



getCurrentSession:

public org.hibernate.classic.Session getCurrentSession() throws HibernateException;




public org.hibernate.classic.Session getCurrentSession() throws HibernateException {
if ( currentSessionContext == null ) {
throw new HibernateException( "No CurrentSessionContext configured!" );
}
return currentSessionContext.currentSession();
}


public interface CurrentSessionContext extends Serializable {

public org.hibernate.classic.Session currentSession() throws HibernateException;



最後 從 Map 中 取連線 :
public Session currentSession() {
Session current = existingSession( factory );
if ( current == null ) {
throw new HibernateException( "No session currently bound to execution context" );
}
return current;
}

或者

public final Session currentSession() throws HibernateException {
Session current = existingSession( factory );
if (current == null) {
current = buildOrObtainSession();
// register a cleanup synch
current.getTransaction().registerSynchronization( buildCleanupSynch() );
// wrap the session in the transaction-protection proxy
if ( needsWrapping( current ) ) {
current = wrap( current );
}
// then bind it
doBind( current, factory );
}
return current;
}



建議你讀讀下面兩個類。它是SessionFactory#getCurrectSession()的實現,它是把Session繫結到了ThreadLocal中。
ThreadLocalSessionContext
CurrentSessionContext

ThreadLocal 作為一個本地變數,當用戶來 獲取一個新的連線時,從連線池中 給予一個新的連線; 當有很多使用者獲取連線時,那麼 就會有 很多 與session 一一對應 的 ThreadLocal 的變數, 可以把 ThreadLocal 看做複本,物件不一樣,但是內容是一樣的。


這是一種 空間換時間的 解決同步問題 的 辦法。