Hibernate的openSession和getCurrentSession区别

原文链接:http://blog.csdn.net/xiao__gui/article/details/7695698

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

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

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

例如:业务逻辑要求向数据库中的用户表增加一个用户,同时向日志表中加入一条日志,而这需要调用DAO的两个方法(UserDao的saveUser和LogDao的saveLog)。这显然是一个事务,也就是如果一个操作出现了问题,就要回滚到初始的状态。那么如何在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_user(id,username)和日志表T_log(id,content),以及它们对应的实体类User、Log及映射文件,这里就不一一贴出代码。

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方法,所以在运行过程中service中session和Dao中的session是同一个对象,是“==”的。这样就可以在servie中开始和提交事务。

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值