您的位置:首页 > 其它

hibernate框架绑定本地的session(八)

2017-11-18 23:45 453 查看
有这么一个业务:保存两个user,在dao层分别写两个方法,在service层调用这两个方法。要保证这两个方法在一个事务里面。

代码如下:

servlet

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
User u1 = new User();
u1.setName("lilei");
u1.setAge(17);

User u2 = new User();
u2.setName("hanmeimei");
u2.setAge(16);

new UserService().save(u1, u2);
}
service
package com.hib.service;

import com.hib.dao.UserDao;
import com.hib.domain.User;

public class UserService {

public void save(User u1, User u2) {
UserDao userDao = new UserDao();
userDao.save1(u1);
int a = 10 / 0;
userDao.save2(u2);
}
}
dao
package com.hib.dao;

import org.hibernate.Session;
import org.hibernate.Transaction;
import com.hib.domain.User;
import com.hib.utils.HibernateUtils;

public class UserDao {
public void save1(User u1) {
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
session.save(u1);
tx.commit();
session.close();
}

public void save2(User u2) {
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
session.save(u2);
tx.commit();
session.close();
}
}
在service层,如果抛出了异常,第一个user能够保存,第二个user不会被保存。这不符合业务要求。

那么在service层开启事务,代码修改如下:

hibernate.cfg.xml添加一个配置项

<!-- 开启绑定本地session -->
<property name="hibernate.current_session_context_class">thread</property>

HibernateUtils添加方法

/**
* 业务层开事务,就用这个
* @return
*/
public static Session getCurrentSession() {
// 从ThreadLocal类中获取到session对象
return FACTORY.getCurrentSession();
}

service

package com.hib.service;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.hib.dao.UserDao;
import com.hib.domain.User;
import com.hib.utils.HibernateUtils;

public class UserService {

public void save(User u1, User u2) {
UserDao userDao = new UserDao();

// 获取session
Session session = HibernateUtils.getCurrentSession();
// 开启事务
Transaction tx = session.beginTransaction();

try {
userDao.save1(u1);
int a = 10 / 0;
userDao.save2(u2);

// 提交事务
tx.commit();
} catch (Exception e) {
e.printStackTrace();
// 出现问题回滚事务
tx.rollback();
} finally {
// 以前,要手动释放资源。现在,session不用关闭,线程结束了,自动关闭
}
}
}
dao
package com.hib.dao;

import org.hibernate.Session;

import com.hib.domain.User;
import com.hib.utils.HibernateUtils;

public class UserDao {
public void save1(User u1) {
Session session = HibernateUtils.getCurrentSession();
session.save(u1);
}

public void save2(User u2) {
Session session = HibernateUtils.getCurrentSession();
session.save(u2);
}
}


Hibernate openSession() 和 getCurrentSession的区别

getHiberanteTemplate 、getCurrentSession和OpenSession 

采用getCurrentSession()创建的Session会绑定到当前的线程中去、而采用OpenSession()则不会。

采用getCurrentSession()创建的Session在commit或rollback后会自动关闭,采用OpenSession()必须手动关闭。

采用getCurrentSession()需要在Hibernate.cfg.xml配置文件中加入如下配置:

如果是本地事物,及JDBC一个数据库:

<propety name=”Hibernate.current_session_context_class”>thread</propety>

如果是全局事物,及jta事物、多个数据库资源或事物资源:

<propety name=”Hibernate.current_session_context_class”>jta</propety>

使用spring的getHiberanteTemplate 就不需要考虑事务管理和session关闭的问题:

openSession创建session时autoCloseSessionEnabled参数为false,即在事物结束后不会自动关闭session,需要手动关闭,如果不关闭将导致session关联的数据库连接无法释放,最后资源耗尽而使程序当掉。              

getCurrentSession创建session时autoCloseSessionEnabled,flushBeforeCompletionEnabled都为true,并且session会同sessionFactory组成一个map以sessionFactory为主键绑定到当前线程。

getCurrentSession():从上下文(配置文件current_session_context_class: thread 使用Connection自动管理;jta(java transaction api) 由Application Server提供的分布式事务管理,Tomcat本身不具备此能力,JBoss、WebLogic具备)找,如果有,则用旧的,否则创建新的,事务提交自动Close;

getCurrentSession本地事务(本地事务:jdbc)时 要在配置文件里进行如下设置:

如果使用的是本地事务(jdbc事务)

<property name="hibernate.current_session_context_class">thread</property>

如果使用的是全局事务(jta事务)

<property name="hibernate.current_session_context_class">jta</property>

 

总之:

 getCurrentSession () 使用当前的session

 openSession()         重新建立一个新的session

 在一个应用程序中,如果DAO 层使用Spring 的hibernate 模板,通过Spring 来控制session 的生命周期,则首选getCurrentSession ()。

源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: