`
ydbc
  • 浏览: 722072 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

例说Hibernate的openSession和getCurrentSession区别

 
阅读更多

很多资料从理论上解释HibernateopenSessiongetCurrentSession的区别,本人写了几个程序来理解它们的区别,在这里和大家分享一下。

简单来说,openSession是打开一个新的session,而getCurrentSession则是获取当前线程里的session,如果没有才打开新的

hibernate可以通过session来控制事务,有了getCurrentSession方法意味着可以将对数据库的操作代码放到不同的地方(不同类的方法中),这样事务控制起来极为方便。在实际开发中,业务逻辑和数据库操作一般会分层,也就是Service层和DAO层。DAO只是单纯的操作数据库,不包含业务逻辑;而Service中的一个业务逻辑可能包含多个数据库操作。

例如:业务逻辑要求向数据库中的用户表增加一个用户,同时向日志表中加入一条日志,而这需要调用DAO的两个方法(UserDaosaveUserLogDaosaveLog)。这显然是一个事务,也就是如果一个操作出现了问题,就要回滚到初始的状态。那么如何在Service层控制事务呢,本文就以此例的代码说明。

Hibernate文档中有个辅助类HibernateUtil,用于获取SessionFactory

package com.xxg;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();
    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration().configure().buildSessionFactory();
        }
        catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}


创建用户表T_userid,username)和日志表T_log(id,content),以及它们对应的实体类UserLog及映射文件,这里就不一一贴出代码。

1、首先使用openSession来测试一下:

public class UserDao {

	public void saveUser(User user){
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); //获取SessionFactory
		Session session = sessionFactory.openSession();// openSession
		session.beginTransaction(); //开始事务
		
		session.save(user);
		
		session.getTransaction().commit(); //事务提交
		session.close(); //关闭session
	}
	
}


public class LogDao {

	public void saveLog(Log log){
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); //获取SessionFactory
		Session session = sessionFactory.openSession();// openSession
		session.beginTransaction(); //开始事务
		
		session.save(log);
		
		session.getTransaction().commit(); //事务提交
		session.close(); //关闭session
	}
	
}


以上两个类是数据库操作Dao层。

public class TestService {
	
	public void save(User user){
		UserDao userDao = new UserDao();
		userDao.saveUser(user);
		
		LogDao logDao = new LogDao();
		Log log = new Log();
		log.setContent("插入一个用户");
		logDao.saveLog(log);
	}

}


以上是service代码,分别调用两个Dao的方法来完成业务逻辑。

public class Test {

	public static void main(String[] args) {

		User user = new User();
		user.setUsername("xxg");
		
		TestService testService = new TestService();
		testService.save(user);
	}

}


最后写一个main方法调用service。

运行,结果如愿。但是,很明显可以看出来,以上代码的service根本没有事务控制。

在LogDao的saveLog方法最后加上一句:

throw new RuntimeException();

public class LogDao {

	public void saveLog(Log log) throws RuntimeException{
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); //获取SessionFactory
		Session session = sessionFactory.openSession();// openSession
		session.beginTransaction(); //开始事务
		
		session.save(log);
		
		
		session.getTransaction().commit(); //事务提交
		session.close(); //关闭session
		
		throw new RuntimeException();
	}
}


再运行一下,发现数据同样还会插入到数据库中。实际上如果在运行期间事务中出现异常,hibernate就会rollback回滚,但是在这里没办法回滚。同样如果插入log出现异常,user表也同样能正常插入数据。

也就是:此时事务的边界在Dao的方法内,而不是在Service方法内。

2.改成getCurrentSession

此时要将事务的边界放到Service中,所以在service中写开始和结束事务的语句,DAO中则不写。

public class LogDao {

	public void saveLog(Log log) throws RuntimeException{
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); //获取SessionFactory
		Session session = sessionFactory.getCurrentSession(); //getCurrentSession
		
		session.save(log);
		
		throw new RuntimeException();
	}
}


public class UserDao {

	public void saveUser(User user){
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); //获取SessionFactory
		Session session = sessionFactory.getCurrentSession();//getCurrentSession
		
		session.save(user);
		
	}
	
}


public class TestService {
	
	public void save(User user){
		
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); //获取SessionFactory
		Session session = sessionFactory.getCurrentSession();//getCurrentSession
		session.beginTransaction();//事务开始
		
		UserDao userDao = new UserDao();
		userDao.saveUser(user);
		
		LogDao logDao = new LogDao();
		Log log = new Log();
		log.setContent("插入一个用户");
		logDao.saveLog(log);
		session.getTransaction().commit();//事务提交
	}

}


以上代码就可以看出来,事务的边界已然在Service中了,因为在这里使用的是getCurrentSession方法,所以在运行过程中servicesessionDao中的session是同一个对象,是“==”的。这样就可以在servie中开始和提交事务。

运行一下,发现回滚了,结果是user表以及log表都没有插入数据。把throw new RuntimeException();去掉再运行,则正常插入。这才是想要的结果。

以上的代码不全,如果想理解这两个方法的区别,不妨动手做做实验。

作者:叉叉哥 转载请注明出处:http://blog.csdn.net/xiao__gui/article/details/7695698

分享到:
评论

相关推荐

    SessionFactory.getCurrentSession与openSession的区别

    博文链接:https://shaqiang32.iteye.com/blog/201918

    getCurrentSession 与 openSession() 的区别

    NULL 博文链接:https://bbxyhaihua.iteye.com/blog/505085

    hibernate 学习笔记

    hibernate 学习笔记: 了解hibernate的基本概念 配置hbm.xml cfg.xml 快速入门案例3: 从domain-xml-数据库表 ...openSession()和getCurrentSession() 线程局部变量模式 transaction事务 在web项目中开发hibernate

    Hibernate3使用经验

    ---------------Hibernate3.0 配置-------------- 1.Hibernate中配置参数 /** * 注意:HQL中使用参数的方法: * 1.根据参数名称来设置参数:匹配名称; * 2.根据参数位置来设置参数:匹配位置; */ //根据参数名称来...

    hibernate操作数据库笔记

    //该方法将到classpath下解析hibernate.cfg.xml中的配置,如果不用Hibernate默认的配置文件名和路径,可在该方法中指定Hibernate配置文件的名称和路径 2.用Configuration对象获取SessionFactory和Session对象:...

    hibernate实现分页查询

    hibernate 分页查询的实现 hibernate 内置的有分页功能 有三个参数 thisnumber一个是当前页数 sumcount是一页显示多少条数据 sql是用来查询的sql语句 public List getPageList(int thisNumber, int sumCount, ...

    struts2.3.x+spring3.1.x+hibernate3.6 demo

    关键问题有几个,第一个HibernateDaoSupport这个没有了,在使用hibernateTemplate的时候,报错误:java.lang.NoSuchMethodError: org.hibernate.SessionFactory.openSession()Lorg/hibernate/classic/Session 很是悲...

    Spring4.0+Hibernate4.0+Struts2.3整合案例

    Spring4.0+Hibernate4.0+Struts2.3整合案例:实现增删改查。 ===================== application.xml: xmlns="http://www.springframework.org/schema/beans" xmlns:xsi=...

    Hibernate1

    对 Hibernate 初体验 1.新建一个java工程,工程名为Hiberante1 2.导入相应的jar包 1)hibernate需要导入这些包 ...Hibernate的初体验就说到这,相信通过上面的例子,我们对hibernate大致有了一些了解了。

    J2EE利用Hibernate采用B/S架构网页设计

    sessionFactory.openSession() : null; threadLocal.set(session); } return session; } /** * Rebuild hibernate session factory * */ public static void rebuildSessionFactory() { try { ...

    hibernate精华教程

    3)通常将每一个Session实例和一个DB事务邦定,也就是说,每执行一个DB事务,都应该先创建一个新的Session实例,不论事务执行成功与否,最后都应该调用Session的close()方法,从而释放Session实例占用的资源。...

    Java面试宝典2020修订版V1.0.1.doc

    9、openSession和getCurrentSession 90 10、拦截器的作用?拦截器和过滤器的区别? 91 11、struts.xml中result的type有哪些类型? 91 12、什么时候用JDBC什么时候用Hibernete; 91 13、hibernate 数据的三个状态 91 ...

    hibernate经典文档

    hibernate 经典文档,学习hibernate 必备的文档,深入浅出,非常实用,强烈推荐!

    Java常见面试题208道.docx

    123.在 hibernate 中 getCurrentSession 和 openSession 的区别是什么? 124.hibernate 实体类必须要有无参构造函数吗?为什么? 十三、Mybatis 125.mybatis 中 #{}和 ${}的区别是什么? 126.mybatis 有几种分页方式...

    Hibernate3.2.6ga 支持Session修改Schema

    修改Hibernate3.2.6ga可以动态通过Session设置Schema Session session=sf.openSession(); session.setSchema("SchemaName"); session.save........ ....... .......

    hibernate session.doc

    例如以下代码先加载一个持久化对象,然后通过delete()方法将它删除: Session session1 = sessionFactory.openSession(); Transaction tx1 = session1.beginTransaction(); // 先加载一个持久化对象 Customer ...

    Hibernate查询语言

    Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); for ( int i=0; i; i++ ) { Customer customer = new Customer(.....); session.save(customer); if ( i % 20 == 0...

    SSH的jar包.rar

    SSH(struts+spring+hibernate)的jar包 SSH 通常指的是 Struts2 做前端控制器,Spring 管理各层的组件,Hibernate 负责持久化层。 一个请求在Struts2框架中的处理大概分为以下几个步骤: 1、客户端初始化一个指向...

Global site tag (gtag.js) - Google Analytics