hibernate不和spring整合单独使用时,session的获取问题很多人都有疑惑,因为我们知道session是非线程安全,若我们想得到线程安全的session,一是使用自己封装的HibernateUtil工具类,threadlocal变量来将线程和session绑定;二是使用hibernate提供的getCurrentSession函数来获取session。这两种方式的使用是有区别的,下面我做个总结。
先给出一个基本的配置文件(下面需要注意的是,数据库必须支持事物,不然结果会有偏差了)
<span style="font-size:14px;"><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://*:3306/*?characterEncoding=utf-8</property>
<property name="hibernate.connection.username">*</property>
<property name="hibernate.connection.password">*</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.show_sql">true</property>
<mapping class="com.hibernatespring.model.TBBS_Test"/>
</session-factory>
</hibernate-configuration></span>
1、自己封装工具类实现save函数
<span style="font-size:14px;">package com.hibernatespring.test;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
public class HibernateUtil {
public static final ThreadLocal session = new ThreadLocal();
public static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static Session currentSession() throws HibernateException {
Session s = (Session) session.get();
if (s == null) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = (Session) session.get();
if (s != null) {
s.close();
}
session.set(null);
}
}</span>
<span style="font-size:14px;"> private void save(TBBS_Test test) throws HibernateException, SQLException {
Session session= (Session) HibernateUtil.currentSession();
session.save(test);
session.flush();
// session.beginTransaction();
// session.save(test);
// session.getTransaction().commit();
HibernateUtil.closeSession();
}</span>
上述代码都能正确执行,在不同的条件下会得到不同的结果。
2、使用hibernate的getCurrentSession实现save函数
<span style="font-size:14px;"> private void saveNew(TBBS_Test test) throws HibernateException, SQLException {
Configuration cfg = new AnnotationConfiguration().configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Session session= sessionFactory.getCurrentSession();
// Transaction s = session.beginTransaction();
session.save(test);
session.flush();
// session.getTransaction().commit();
}</span>
执行函数抛出异常,org.hibernate.HibernateException: No CurrentSessionContext configured!,解决这个问题需要在配置文件中加入这句
<span style="font-size:14px;"><property name="hibernate.current_session_context_class">thread</property></span>
再执行上面的函数,再次抛出异常org.hibernate.HibernateException: save is not valid without active transaction,很明显这个意思是必须在事务中执行,换成事务执行方式插入记录成功,
3、两者区别总结,
1)getCurrentSession必须配置thread上下文
2)getCurrentSession必须在事务中执行
3)getCurrentSession不需要手动关闭