首先OpenSession()是永远打开一个新的session,这个可以通过下面的方法来证明:
@Test
public void test() {
Student s = new Student();
StudentPK pk = new StudentPK();
s.setPk(pk);
s.setAge(23);
s.setClasses(1);
pk.setId(1);
pk.setName("moluo");
Session session = sf.openSession();
Session session1 = sf.openSession();
session.beginTransaction();
session.save(s);
System.out.println(session == session1); //输出结果为false;
session.getTransaction().commit();
session.close();
session1.close();
}
输出结果为false,显然这俩session不是同一个session,所以openSession()每次都是new一个新的session。
其次,OpenSession()打开一个session以后必须显式的去关闭(session.close())。
再来看看getCurrentSession(),它是从上下文里找,如果有session,它就使用原来的session,如果没有它就new一个session。怎么证明呢?来看看下面这个例子:
@Test
public void test() {
Student s = new Student();
StudentPK pk = new StudentPK();
s.setPk(pk);
s.setAge(23);
s.setClasses(1);
pk.setId(1);
pk.setName("moluo");
Session session = sf.getCurrentSession();
Session session1 = sf.getCurrentSession();
session.beginTransaction();
session.save(s);
System.out.println(session == session1); //输出结果为true;
session.getTransaction().commit();
//session.close();
//session1.close();
}
输出结果为true,显然这俩session是同一个session,否则输出结果就是false了,也就是说当上下文如果存在一个session,它就使用原来的session。在事物没有提交或者回滚之前,无论我们拿多少次session,它们都是同一个session,但如果提交或者回滚了,再拿就是新的session了。
另外,getCurrentSession()不需要我们显式的去关闭,因为当事物提交(session.getTransaction().commit())或者回滚之后,会自动的帮我们去关闭session。如果我们显式的去关闭session,就有可能会出现问题,所以不要去多此一举。
既然提到了他俩都可以获取session,那么他俩获取到的session是否为同一个session呢?再看下面的例子:
@Test
public void test() {
Student s = new Student();
StudentPK pk = new StudentPK();
s.setPk(pk);
s.setAge(23);
s.setClasses(1);
pk.setId(1);
pk.setName("moluo");
Session session = sf.openSession();
Session session1 = sf.getCurrentSession();
session.beginTransaction();
session.save(s);
System.out.println(session == session1); //输出结果为false;
session.getTransaction().commit();
//session.close();
}
输出结果为false,证明他俩不是同一个session,有些朋友就有可能会有疑问了,session1是通过getCurrentSession()得到的,而getCurrentSession()不是通过上下文获取session吗?上下文不是openSession(),不是已经有了一个session了吗?实际上session是一个接口,通过这俩方式得到的session的具体实现方式是不一样的,所以输出结果为false。
讲到getCurrentSession()会从上下文里获取session,那么上下文的配置在哪呢?实际上在sf = new AnnotationConfiguration().configure().buildSessionFactory();这步就已经调用配置文件hibernate.cfg.xml了,如果配置文件不是这个默认名,而是hibernate.xml,那么就必须改成:
sf = new AnnotationConfiguration().configure(“hibernate.xml”).buildSessionFactory();也就是说在configure()方法就调用了配置文件。
回归正题:上下文配置在配置文件的:
<property name="current_session_context_class">thread</property>
这里一共有4个可选的参数,分别是:jta,thread,custom,managed。前两者比较常用,后两者很少用到。
thread使用connection,用于单数据库连接事物管理,而jta(java transaction api)运行时需要application server提供支持,它主要用于多数据库,分布式事物管理,用于界定事物边界。
另外,getCurrentSession()创建的session会绑定到当前线程中,而openSession()不会绑定。
最后还有一点就是:openSession()可以在不开启事物的情况下执行,而getCurrentSession()不行。(这个是在网上看来的,未经佐证!)
尊重版权,转载请不要删除下方二维码并注明本文链接
欢迎关注行者摩罗微信公众号(xingzhemoluo),共同交流编程经验,扫描下方二维码即可;