本帖最后由 大山哥哥 于 2018-10-25 20:25 编辑
关于hibernate的使用,相信大家还是比较了解的,那么今天咱们换个角度来分析下问题. 正常情况下,我们在使用hibernate的时候,核心就是获取一个session对象,然后通过session对象去操作我们数据库.那么如何获取session呢? 方式1: [Java] 纯文本查看 复制代码 new Configuration().configure().buildSessionFactory().openSession(); 方式2: [Java] 纯文本查看 复制代码 new Configuration().configure().buildSessionFactory().getCurrentSession();
方式1的特点是每次执行都会去创建一个新的session,而方式2是每次操作都会获取和线程绑定的session,但是方式2有个前提,需要在Hibernate的核心配置中去配置一段如下 [XML] 纯文本查看 复制代码 <property name="hibernate.current_session_context_class">thread</property>
Ok,那么接下来咱们则从源码角度带着大家来看下为什么通过一个配置和一个api就能实现我们session和线程绑定.其实需要借助于一个api,叫ThreadLocal,所以接下来咱们就正式开始来详细翻下源码~
sessionFactory.getCurrentSession();
我们发现SessionFactory是一个接口,所以只能进入具体实现类去寻找.通过集成结构我们则找到了SessionFactoryImpl这个类. 这个类的继承结构可以看出,该类实现SessionFactoryImplementor接口,该接口又继承自SessionFactory.
当然在getCurrentSession()方法中发现最后返回的是currentSessionContext.currentSession()方法. 所以我们则开始关注下currentSessionContext对象是谁. 因为代码太长就把相关代码粘贴出来 [Java] 纯文本查看 复制代码 public final class SessionFactoryImpl implements SessionFactoryImplementor{
private final transient CurrentSessionContext currentSessionContext;
public SessionFactoryImpl(final MetadataImplementor metadata, SessionFactoryOptions options) {
LOG.debug( "Building session factory" );
...省略大量代码
currentSessionContext = buildCurrentSessionContext();
...省略大量代码
}
} 至此我们则定位到这个buildCurrentSessionContext()方法中,ok,继续往里追 Ok,当然图片可能没有截取很完整但是关键的都在了,首先看标记1 Environment.CURRENT_SESSION_CONTEXT_CLASS对应的常量值为hibernate.current_session_context_class 其实到这里我们就已经发现了,这个值和我们当初在hibernate的配置文件中的配置信息是一样的. 而我们在配置文件中配置的值为thread,继续上面的源码往下看会发现标记2,我们那thread和读取配置文件获取的impl字符串做比较.因为我们填的是thread,会走进标记2的代码段. [Java] 纯文本查看 复制代码 else if ( "thread".equals( impl ) ) {
return new ThreadLocalSessionContext( this );
} 在这里,我们终于看到了创建session对象的类是谁了.ThreadLocalSessionContext. 到此为止,我们已经明确了,使用Hibernate的getCurrentSession()方法获取到的session其实是由ThreadLocalSessionContext中的currentSession()方法来获取到的,由于篇幅的原因,下次的帖子中则会带着大家继续深入分析我们ThreadLocalSessionContext如何做到将session和thread进行绑定~其实就围绕着一个对象ThreadLocal.
|