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
// 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,
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 看做複本,物件不一樣,但是內容是一樣的。
這是一種 空間換時間的 解決同步問題 的 辦法。