过完五一长假,花了四天的时间来学习Hibernate框架的使用,作为门外汉,先是从sourceforg.net下载Hibernate3.2,先看官方文档,只有一个提纲,了解了一下各个包的结构,便开始根据Toturial实践,基本掌握了它的使用方法之后,盟生了实现自己的SessionFactory和ConnectionProvider的想法。
闲话少说,要实现我的SessionFactory和ConnectionProvider,不深入了解该体系结构是不行的,先从源代码分析开始:
首先从org.hibernate.cfg.Configuration.java开始,使用Hibernate框架实现应用程序,首先就要与org.hibernate.cfg.Configuration打交道,要使用
Configuration.buildSessionFactory()方法获得一个SessionFactory,截取代码片段如下:
1
public SessionFactory buildSessionFactory() throws HibernateException
{
2


3
return new SessionFactoryImpl(
4
this,
5
mapping,
6
settings,
7
getInitializedEventListeners()
8
);
9
}
上面的代码片断省略了读取Hibernate配置的代码,从这个我们可以知道,Configuration类buildSessionFactory()方法实际上返回了SessionFactory接口的实现SessionFactoryImpl。
当我们得到了一个SessionFactory接口的实现SessionFactoryImpl,就要调用它的getCurrentSession()方法来获得一个Session,接下来转到org.hibernate.impl.SessionFactoryImpl.java,来看看getCurrentSession()方法的实现,代码片段如下:
1
public org.hibernate.classic.Session getCurrentSession() throws HibernateException
{
2
if ( currentSessionContext == null )
{
3
throw new HibernateException( "No CurrentSessionContext configured!" );
4
}
5
return currentSessionContext.currentSession();
6
}
在该方法中,SessionFactoryImpl将获得Session的工作委托给了currentSessionContext.currentSession(),currentSessionContext为何物?其定义为:
org.hibernate.context.CurrentSessionContext;在SessionFactoryImpl的构造函数中,可以看到:
currentSessionContext = buildCurrentSessionContext();

马上追溯到buildCurrentSessionContext()方法,代码片段如下:
1
private CurrentSessionContext buildCurrentSessionContext()
{
2
String impl = properties.getProperty( Environment.CURRENT_SESSION_CONTEXT_CLASS );
3
// for backward-compatability
4
if ( impl == null && transactionManager != null )
{
5
impl = "jta";
6
}
7
8
if ( impl == null )
{
9
return null;
10
}
11
else if ( "jta".equals( impl ) )
{
12
if ( settings.getTransactionFactory().areCallbacksLocalToHibernateTransactions() )
{
13
log.warn( "JTASessionContext being used with JDBCTransactionFactory; auto-flush will not operate correctly with getCurrentSession()" );
14
}
15
return new JTASessionContext( this );
16
}
17
else if ( "thread".equals( impl ) )
{
18
return new ThreadLocalSessionContext( this );
19
}
20
else if ( "managed".equals( impl ) )
{
21
return new ManagedSessionContext( this );
22
}
23
else
{
24
try
{
25
Class implClass = ReflectHelper.classForName( impl );
26
return ( CurrentSessionContext ) implClass
27
.getConstructor( new Class[]
{ SessionFactoryImplementor.class } )
28
.newInstance( new Object[]
{ this } );
29
}
30
catch( Throwable t )
{
31
log.error( "Unable to construct current session context [" + impl + "]", t );
32
return null;
33
}
34
}
35
}
36
从这里可以发现,SessionFactoryImpl用反射实现了CurrentSessionContext接口的动态装配。
接下来,暂时将视线从SessionFactoryImpl移开,以org.hibernate.context.JTASessionContext为代表,看CurrentSessionContext接口是如何实现
的currentSession()方法的,打开org.hibernate.context.JTASessionContext.java,找到currentSession(),代码片段如下:
1
public Session currentSession() throws HibernateException
{
2


3
if ( currentSession == null )
{
4
currentSession = buildOrObtainSession();
5


6
}
7


8
return currentSession;
9
}
转移到buildOrObtainSession()方法,
1
protected Session buildOrObtainSession()
{
2
return factory.openSession(
3
null,
4
isAutoFlushEnabled(),
5
isAutoCloseEnabled(),
6
getConnectionReleaseMode()
7
);
8
}
前面SessionFactoryImpl.buildCurrentSessionContext()方法有new JTASessionContext( this ),而此时的factory.openSessio()就是SessionFactoryImpl.openSessio()了。
将目光焦点回到org.hibernate.impl.SessionFactoryImpl.java, SessionFactoryImpl.openSessio()的实现如下:
1
private SessionImpl openSession(
2
Connection connection,
3
boolean autoClose,
4
long timestamp,
5
Interceptor sessionLocalInterceptor
6
)
{
7
return new SessionImpl(
8
connection,
9
this,
10
autoClose,
11
timestamp,
12
sessionLocalInterceptor == null ? interceptor : sessionLocalInterceptor,
13
settings.getDefaultEntityMode(),
14
settings.isFlushBeforeCompletionEnabled(),
15
settings.isAutoCloseSessionEnabled(),
16
settings.getConnectionReleaseMode()
17
);
18
}