之前讲解的openSession()是获取Session的方式一:
开启事务: 开启事务属于数据库操作,但写在 dao 里面导致每个方法开启一次事务,所以一般在 service 开启, 方案:
通过参数的方式传递下去(确保底层使用的都是同样一个session)
把Connection绑定到ThreadLocal对象中,多线程能够保持使用各自的一个对象。如果set是同一个对象,get还是共享对象。
开发流程:
第一步:配置开启支持本地线程绑定
开启事务并传递session对象,框架提供了ThreadLocal方式。
<property name="hibernate.current_session_context_class">thread</property>
注意事项:
使用这种方式,所有的功能必须使用事务。
第二步:获取session
使用SessionFactory的getCurrentSession() 获取当前的Session对象。该对象不用手动关闭,线程结束了,会自动关闭。
完善HibernateUtils 工具类:
public class HibernateUtils {
private static SessionFactory sessionFactory ;
static {
Configuration configure = new Configuration().configure("hibernate.cfg.xml");
sessionFactory=configure.buildSessionFactory();
}
public static Session getSession(){
return sessionFactory.openSession();
}
//获取session方式二,使用这个session必须开启事务
public static Session getCuurentSession(){
//受线程绑定,也就是在多线程环境下,是线程安全的。
return sessionFactory.getCurrentSession();
}
}
第三步:开发
注意:
必须开启事务
这种方式查询也必须使用事务,可以设置为只读。
如过不开启事务会报错:
image.png核心代码如下:
@Test
public void testQueryByAnotherSession(){
Session cuurentSession = HibernateUtils.getCuurentSession();
String sql="from TUserInfo where uId=:uid";
Query<TUserInfo> query = cuurentSession.createQuery(sql, TUserInfo.class);
query.setParameter("uid",15L);
TUserInfo tUserInfo = query.uniqueResult();
System.out.println(tUserInfo);
}
运行:
image.png
发现报错了, 报错信息很明显,这个时候需要我们去加上事物处理。
修改代码 加上事物如下:
image.png
正常输出:
image.png
扩展(对比两个session)
getCurrentSession多线程安全
openSession多线程不安全
public void testSession(){
//在用一个线程内,用HibernateUtils.getCuurentSession()取得到的是一样的session
Session cuurentSession = HibernateUtils.getCuurentSession();
System.out.println(cuurentSession);
Session cuurentSession1 = HibernateUtils.getCuurentSession();
System.out.println(cuurentSession1);
System.out.println("对比结果:");
System.out.println(cuurentSession==cuurentSession1);
Session session = HibernateUtils.openSession();
Session session2 = HibernateUtils.openSession();
System.out.println("openSession对比结果:");
System.out.println(session==session2);
}
输出结果如下所示
image.png
网友评论