hibernate一般使用getcurrentsession还是opensession写session的增删改查查?current是不是会占

openSession和getCurrentSession的比较
在比较openSession和getCurrentSession这两个方法之前,我们先认识一下这两个方法。
在进行配置信息管理时,我们一般进行一下简单步骤:
&&&Configuration
cfg = new Configuration();& // 获得配置信息对象
&&&SessionFactory
sf = cfg.configure().buildSessionFactory(); //解析并建立Session工厂
&&1.&Session
session = sf.getCurrentSession(); // 获得Session
& 2. Session session = sf.openSession(); //
打开Session
对于上述的两个方法,有以下区别:
& 1. openSession
从字面上可以看得出来,是打开一个新的session对象,而且每次使用都是打开一个新的session,假如连续使用多次,则获得的session不是同一个对象,并且使用完需要调用close方法关闭session。
& 2. getCurrentSession
,从字面上可以看得出来,是获取当前上下文一个session对象,当第一次使用此方法时,会自动产生一个session对象,并且连续使用多次时,得到的session都是同一个对象,这就是与openSession的区别之一,简单而言,getCurrentSession
就是:如果有已经使用的,用旧的,如果没有,建新的。
:在实际开发中,往往使用getCurrentSession多,因为一般是处理同一个事务(即是使用一个数据库的情况),所以在一般情况下比较少使用openSession或者说openSession是比较老旧的一套接口了;
对于getCurrentSession 来说,有以下一些特点:
1.用途,界定事务边界
2.事务提交会自动close,不需要像openSession一样自己调用close方法关闭session
3.上下文配置(即在hibernate.cfg.xml)中,需要配置:
name="current_session_context_class"&thread&/property&
(需要注意,这里的current_session_context_class属性有几个属性值:jta&、
thread 常用 , custom、managed 少用 &)
a).thread使用connection
单数据库连接管理事务
b).jta (java& transaction
api) Java 分布式事务管理 (多数据库访问),jta 由中间件提供(JBoss WebLogic 等, 但是tomcat
下面是openSession 和 getCurrentSession 简单实例的区别 :
1.openSession方式 :
org.hibernate.S
org.hibernate.SessionF
org.hibernate.cfg.C
com.hibernate.model.S& // 注意包路径
&& public class StudentTest
& &public static void
main(String[] args) {
&& Student s = new
Student();
&&&s.setId(1);
&&&s.setName("s1");
&&&s.setAge(1);
&&&Configuration
cfg = new Configuration();& // 获得配置信息对象
&&&SessionFactory
sf = cfg.configure().buildSessionFactory(); //解析并建立Session工厂
&&&Session
session = sessionFactory.openSession(); // 打开Session
&&&session.beginTransaction();&
// 看成一个事务,进行操作
&&&session.save(s);&
// 会找到 Student 这个类,寻找set方法
&&&session.getTransaction().commit();
// 提交对数据的操作
&&&session.close();
&& sf.close();
2.getCurrentSession方式 :
org.hibernate.S
org.hibernate.SessionF
org.hibernate.cfg.C
com.hibernate.model.S& // 注意包路径
&& public class StudentTest
& &public static void
main(String[] args) {
&& Student s = new
Student();
&&&s.setId(1);
&&&s.setName("s1");
&&&s.setAge(1);
&&&Configuration
cfg = new Configuration();& // 获得配置信息对象
&&&SessionFactory
sf = cfg.configure().buildSessionFactory(); //解析并建立Session工厂
&&&Session
session = sessionFactory.getCurrentSession(); // 打开Session
&&&session.beginTransaction();&
// 看成一个事务,进行操作
&&&session.save(s);&
// 会找到 Student 这个类,寻找set方法
&&&session.getTransaction().commit();
// 提交对数据的操作
&& sf.close();
Student 类代码 :
package com.hibernate.
public class Student {
&private S
&public int getId() {
&public void setId(int id) {
&&this.id =
&public String getName() {
&public void setName(String name) {
&&this.name =
&public int getAge() {
&public void setAge(int age) {
&&this.age =
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。下次自动登录
现在的位置:
& 综合 & 正文
由openSession、getCurrentSession和HibernateDaoSupport浅谈Spring对事物的支持
Spring和Hibernate的集成的一个要点就是对事务的支持,openSession、getCurrentSession都是编程式事务(手动设置事务的提交、回滚)中重要的对象,HibernateDaoSupport则提供了更方便的声明式事务支持。
Hibernate中最重要的就是Session对象的引入,它是对jdbc的深度封装,包括对事务的处理,Session对象通过SessionFactory来管理,openSession和getCurrentSession是管理session的重要的方法。
openSession和getCurrentSession的根本区别在于有没有绑定当前线程,所以,使用方法有差异:
* openSession没有绑定当前线程,所以,使用完后必须关闭,
* currentSession和当前线程绑定,在事务结束后会自动关闭。
关于事务的边界和传播:
通常情况下事务的边界需要设置在业务逻辑处理层中,但是,如果在一个业务中涉及到多个业务逻辑层之间的方法,且需要在同一个事务中运行,那么,这就涉及到了事务的传播性。
如果使用openSession,就要在dao层的方法中传递session,而这种做法是很糟糕的,首先增加了参数的个数,另外,方法是否需要事务,完全是可以当做一种独立的服务抽离出的。
因为currentSession是线程级别的,所以,只要业务逻辑方法在同一个线程中,就不会担心上面的问题。这也是currentSession的一个优越处之一。
使用currentSession:
1.在配置文件中将线程配置成Thread级别的。
&propertyname="hibernate.current_session_context_class"&thread&/property&
2.调用sessionFactory的getCurrentSession方法:
publicvoid addUser(User user) {
Session session =
session =HibernateUtils.getSessionFactory().getCurrentSession();
session.beginTransaction();
session.save(user);
Loglog = new Log();
log.setType("操作日志");
log.setTime(new Date());
log.setDetail("XXX");
LogManager logManager = newLogManagerImpl();
logManager.addLog(log);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
使用openSession:
public void addUser(User user) {
Sessionsession =
session= HibernateUtils.getSession();
session.beginTransaction();
// 若干操作…………
session.getTransaction().commit();
}catch(Exceptione) {
e.printStackTrace();
session.getTransaction().rollback();
HibernateUtils.closeSession(session);
使用HibernateDaoSupport声明式事务:
Spring与Hibernate的集成使用最多的是HibernateDaoSupport,它对session的获取以及事务做了进一步的封装,只需要关注dao的实现,而不用担心某个地方的事务是否关闭。
this.getHibernateTemplate().save(user);
关于异常与事务回滚:
Spring在遇到运行期异常(继承了RuntimeException)的时候才会回滚,如果是Exception(如用户输入密码错误)抛出就好,事务会继续往下进行。
Spring对异常的处理的灵活性还是比较高的,可以配置遇到某个Exception进行回滚,某个RuntimeException不回滚,但是对于EJB就没有这么灵活了,EJB相当于是固定的套餐。
public void addUser(User user)
throws Exception {
this.getHibernateTemplate().save(user);
//若干操作……
throw new Exception();
public void addUser(User user) {
this.getHibernateTemplate().save(user);
//若干操作……
throw new RuntimeException();
Spring与Hibernate的集成,使用HibernateDaoSupport的配置:
在ssh框架应用中,Spring与Hibernate的事务集成基本上是比较固定的,我们把事务的集成单独配置到applicationContext-common.xml中:
&?xml version="1.0"encoding="UTF-8"?&
&beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.0.xsd"&
&!--配置SessionFactory --&
&beanid="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"&
&propertyname="configLocation"&
&value&classpath:hibernate.cfg.xml&/value&
&/property&
&!--配置事务管理器 --&
&beanid="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager"&
&propertyname="sessionFactory"&
&refbean="sessionFactory"/&
&/property&
&!--那些类那些方法使用事务 --&
&aop:config&
&aop:pointcutid="allManagerMethod" expression="execution(*com.bjpowernode.usermgr.manager.*.*(..))"/&
&aop:advisorpointcut-ref="allManagerMethod" advice-ref="txAdvice"/&
&/aop:config&
&!--事务的传播特性 --&
&tx:adviceid="txAdvice" transaction-manager="transactionManager"&
&tx:attributes&
&tx:methodname="add*" propagation="REQUIRED"/&
&tx:methodname="del*" propagation="REQUIRED"/&
&tx:methodname="modify*" propagation="REQUIRED"/&
&tx:methodname="*" propagation="REQUIRED"read-only="true"/&
&/tx:attributes&
&/tx:advice&
因为在hibernate.cfg.xml中添加了如下配置,所以,在tomcat等容器启动的时候,会自动将相应的bean对象创建。
&propertyname="hibernate.hbm2ddl.auto"&update&/property&
applicationContext-beans.xml:
通常将业务逻辑对实现类的引用单独的xml文件中,同时,在实现类中不能忽略sessionFactory工厂的注入。
&?xml version="1.0"encoding="UTF-8"?&
&beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.0.xsd"&
&beanid="userManager" class="com.bjpowernode.usermgr.manager.UserManagerImpl"&
&propertyname="sessionFactory" ref="sessionFactory"/&
&propertyname="logManager" ref="logManager"/&
&beanid="logManager"class="com.bjpowernode.usermgr.manager.LogManagerImpl"&
&propertyname="sessionFactory" ref="sessionFactory"/&
事务传播特性:
为了保证调用的业务逻辑方法都使用同一个事务,通常都使用REQUIRED这个级别,它表示:如果上一个方法中有事务,就直接使用,如果没有,就创建一个事务,这样,一旦事务创建了后,后续调用的方法就不会再创建。
其他的事务传播特性见下表:
Spring事务的隔离级别:
1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。
另外四个与JDBC的隔离级别相对应。
2. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。
这种隔离级别会产生脏读,不可重复读和幻像读。
3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
5. ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。
除了防止脏读,不可重复读外,还避免了幻像读。
事务隔离级别主要应用在对大数据的处理方面,与锁的机制是密不可分的,这里不赘述。
&&&&推荐文章:
【上篇】【下篇】1 单独使用hibernate处理事务
本来只用hibernate开发,从而可以省了DAO层实现数据库访问和跨数据库,也可以对代码进行更好的封装,当我们web中单独使用hibernate时,我们需要单独的处理hibernate的事务,我是使用filter来对事务进行控制的:
单独使用hibernate使用filter进行事务控制:
HibernateSessionFilter.java
public class HibernateSessionFilter implements Filter {
public void destroy() {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
Session session = HibernateUtils.openSession();
Transaction tx =
tx = session.beginTransaction();
chain.doFilter(request, response);
tx.commit();
} catch (Exception e) {
if (tx != null) {
tx.rollback();
throw new RuntimeException(e);
} finally {
HibernateUtils.closeAndRemoveSession();
public void init(FilterConfig arg0) throws ServletException {
&filter-name&hibernateSessionFilter&/filter-name&
&filter-class& syx.jpkc.filter.HibernateSessionFilter&/filter-class&
&filter-mapping&
&filter-name&hibernateSessionFilter&/filter-name&
&url-pattern&*.syx&/url-pattern&
&url-pattern&*.jsp&/url-pattern&
&url-pattern&*.eve&/url-pattern&
&/filter-mapping&
我主要在servlet(*.syx,*.eve)和jsp页面(没用struts)需要和数据库操作,所以需要使用事务处理。
上面我们还用到了一个 HibernateUtils的小工具类,主要为了获取Session对象和一点优化:
HibernateUitls.java
public class HibernateUtils {
private static Map&Thread, Session& sessionM
private static SessionFactory sessionF
sessionMap = new HashMap&Thread, Session&();
sessionFactory = new Configuration().configure().buildSessionFactory();
* can only use in web filter, beause it should remove and clear resources
public static Session openSession() {
System.out.println(Thread.currentThread().getStackTrace()[1] + " run in " + new Date());
Session session = sessionMap.get(Thread.currentThread());
if (session == null) {
session = sessionFactory.openSession();
sessionMap.put(Thread.currentThread(), session);
public static Session getCurrentSession() {
return sessionMap.get(Thread.currentThread());
public static void closeAndRemoveSession() {
System.out.println(Thread.currentThread().getStackTrace()[1]+ " run in " + new Date());//
Session session = sessionMap.remove(Thread.currentThread());
if (session != null) {
session.close();
2 hibernate整合进spring后的事务处理
spring事物处理的方式有很多,详见:
介绍常用的:
spring annotation声明式的事务管理
1) 事物处理层?
比如保存一个User,可以在Service层和DAOImpl层实现:
public void save(User u) {
userDAO.save(u);
public void save(User u) {
System.out.println("save user from:" + this);
Session s = sessionFactory.openSession();
s.beginTransaction();
s.save(u);
s.getTransaction().commit();
s.close();
假如我们还有个日志记录,没保存一个User对象,要写入日志进入数据库。
而save(log) 和 save(user)必须处在同一事务中,所以不能放在DAOImpl层,事务处理在Service层。
2) 一般的事务处理
Session sess = factory.openSession();
tx = sess.beginTransaction();
//do some work
//save(user);
//save(log);
tx.commit();
} catch (Exception e) {
if (tx!=null) tx.rollback();
} finally {
sess.close();
并且要在实现层中的save()方法中也要加入事务处理,如果出出现异常要throws给上级处理!
并且实现层中的session必须使用openCurrentSession()得到。
Session s = sessionFactory.getCurrentSession();
s.save(u);
3) spring annotation事务处理
Beans.xml中引入相应的xml命名空间和相应配置:
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
&tx:annotation-driven transaction-manager="txManager"/&
&bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"&
&property name="sessionFactory" ref="sessionFactory" /&
&bean id="dataSource"
class="mons.dbcp.BasicDataSource"
destroy-method="close"&
&property name="driverClassName"
value="${jdbc.driverClassName}" /&
&property name="url" value="${jdbc.url}" /&
&property name="username" value="${jdbc.username}" /&
&property name="password" value="${jdbc.password}" /&
&bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"&
&property name="dataSource" ref="dataSource" /&
&property name="annotatedClasses"&
&value&com.syx.model.User&/value&
&value&com.syx.model.Log&/value&
&/property&
&property name="hibernateProperties"&
&prop key="hibernate.dialect"&org.hibernate.dialect.MySQLDialect&/prop&
&prop key="hibernate.show_sql"&true&/prop&
&prop key="current_session_context_class"&thread&/prop&
&/property&
Save方法:
public void save(User u) {
Session s = sessionFactory.getCurrentSession();
s.save(u);
public void save(Log log) {
Session s = sessionFactory.getCurrentSession();
s.save(log);
Service层处理:
@Component("userService")
public class UserService {
UserDAO userDAO =
LogDAO logDAO =
public LogDAO getLogDAO() {
return logDAO;
@Resource(name="logDAOMySQLImpl")
public void setLogDAO(LogDAO logDAO) {
this.logDAO = logDAO;
@Transactional
public void save(User u) {
userDAO.save(u);
Log log = new Log();
log.setMsg(u.getName() + " saved in " + new Date());
logDAO.save(log);
public UserDAO getUserDAO() {
return userDAO;
@Resource(name="userDAOMySQLImpl")
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
4) @Transactional详解
什么时候rollback
运行期异常,非运行期异常不会触发rollback
必须uncheck (没有catch)
不管什么异常,只要你catch了,spring就会放弃管理
事务传播特性:propagation_required
默认是 REQUIRED ,意思是有我们就用现成的,没的我们就创造一个,其他详细见文档
spring xml声明式的事务管理
配置环境和annotation版本一致,只是在用@Transactional处注释调用,在beans.xml中加入如下配置:
&!-- spring tranception xml config --&
&aop:config&
&aop:pointcut id="serviceOperation"
expression="execution(* com.syx.service..*.*(..))" /&
&aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" /&
&/aop:config&
&tx:advice id="txAdvice"
transaction-manager="txManager"&
&tx:attributes&
&tx:method name="getUser" read-only="true" /&
&tx:method name="save" /&&!-- 相当于在上面切面pointcut@Transactional效果 --&
&/tx:attributes&
&/tx:advice&
3 hibernateTemplate.getSessionFactory().getCurrentSession()
我们使用spring和hibernate结合,操作数据库最常用可能是HibernateTemplate,HibernateTemplate中集成了很多使用的方法,可惜的是没的createQuery方法,也许我们使用hibernate的时候喜欢使用Query,我们可能会封装hibernateTemplate.getSessionFactory().getCurrentSession()方法得到Session,session创建Query,这是一个方法,但你应该会得到异常 &createQuery without an active transaction&,因为使用hibernateTemplate.getSessionFactory().getCurrentSession(),你是使用的hibernate的事务管理,而你指望spring管理的事务是hibernateTemplate,所以你会提示没有打开事务的异常,解决方法:1)使用hibernate事务处理,就像上面单独使用hibernate一样,但这也许不是你想要的。2)使用hibernateTemplate的HibernateCallBack回调:
return hibernateTemplate.executeWithNativeSession(
new HibernateCallback&List&T&&() {
List&T& doInHibernate(Session session)
throws HibernateException, SQLException {
return session.createQuery
("FROM " + entityClass.getName() + " WHERE id IN (:ids)")//
.setParameterList("ids", idList).list();
实际上hibernateTemplate中封装的find方法也很强大,如果熟练使用完全可以替代createQuery的。
如果出现异常:对同一个集合处理不能使用2个session,这是因为getCurrentSession方法出错,导致打开一个新的session,检查配置文件,如果使用tomcat+spring+hibernate 配置hibernate.current_session_context_class 最好为thread,虽然支持jta,配置比较麻烦,而且jta支持多个sessionFactory,即可以跨数据库,比较强大!
如果hibernate+spring出现session没有提交情况,应该是你让spring负责事务处理,而你有使用了hibernate的session,从而脱离spring事务处理,即没的begintransaction和commit之类的操作了。
阅读(...) 评论()1、openSession 每一次获得的是一个全新的session对象,而getCurrentSession获得的是与当前线程绑定的session对象
package cn.kiwifly.
import org.hibernate.SessionF
import org.hibernate.cfg.C
import org.hibernate.classic.S
import cn.kiwifly.util.MySessionF
public class View {
public static void main(String[] args) {
Configuration configuration = new Configuration().configure();
SessionFactory sf = configuration.buildSessionFactory();
Session sessionOpen1 = sf.openSession();
Session sessionOpen2 = sf.openSession();
Session sessionThread1 = sf.getCurrentSession();
Session sessionThread2 = sf.getCurrentSession();
System.out.println(sessionOpen1.hashCode() + &&--------&& + sessionOpen2.hashCode());
System.out.println(sessionThread1.hashCode() + &&--------&& + sessionThread2.hashCode());
上面代码输出结果:
&--------&
&--------&
2、openSession不需要配置,而getCurrentSession需要配置
1中代码如果直接运行会报错,要在hibernate.cfg.xml中加入如下代码才行
&property name=&current_session_context_class&&thread&/property&
这里我们是让session与当前线程绑定,这里的线程范围应该是一次浏览器的会话过程,也就是说打开网站和关闭浏览器这个时间段。
3、openSession需要手动关闭,而getCurrentSession系统自动关闭
openSession出来的session要通过:
session.close(); 而getSessionCurrent出来的session系统自动关闭,如果自己关闭会报错
4、Session是线程不同步的,要保证线程安全就要使用getCurrentSession
阅读(...) 评论()

我要回帖

更多关于 hibernate4的增删改查 的文章

 

随机推荐