单独使用hibernate处理事务

  本来只用hibernate开发,从而可以省了DAO层实现数据库访问和跨数据库,也可以对代码进行更好的封装,当我们web中单独使用hibernate时,我们需要单独的处理hibernate的事务,我是使用filter来对事务进行控制的:

  单独使用hibernate使用filter进行事务控制:

01 public class HibernateSessionFilter implements Filter {

02

03     public void destroy() {

04

05     }

06

07     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,

08             ServletException {

09         Session session = HibernateUtils.openSession();

10         Transaction tx = null;

11         try {

12             tx = session.beginTransaction();

13             chain.doFilter(request, response);

14             tx.commit();

15         } catch (Exception e) {

16             if (tx != null) {

17                 tx.rollback();

18             }

19             throw new RuntimeException(e);

20         } finally {

21             HibernateUtils.closeAndRemoveSession();

22         }

23     }

24

25     public void init(FilterConfig arg0) throws ServletException {

26     }

27

28 }

  web.xml

01 <filter>

02   <filter-name>hibernateSessionFilter</filter-name>

03   <filter-class> syx.jpkc.filter.HibernateSessionFilter</filter-class>

04 </filter>

05 <filter-mapping>

06   <filter-name>hibernateSessionFilter</filter-name>

07   <url-pattern>*.syx</url-pattern>

08   <url-pattern>*.jsp</url-pattern>

09   <url-pattern>*.eve</url-pattern>

10 </filter-mapping>

  我主要在servlet(*.syx,*.eve)和jsp页面(没用struts)需要和数据库操作,所以需要使用事务处理。

  上面我们还用到了一个 HibernateUtils的小工具类,主要为了获取Session对象和一点优化:

  HibernateUitls.java

01 public class HibernateUtils {

02     private static Map<Thread, Session> sessionMap;

03     private static SessionFactory sessionFactory;

04     static {

05         sessionMap = new HashMap<Thread, Session>();

06         sessionFactory = new Configuration().configure().buildSessionFactory();

07     }

08

09     /**

10      * can only use in web filter, beause it should remove and clear resources

11      * @return

12      */

13     public static Session openSession() {

14         System.out.println(Thread.currentThread().getStackTrace()[1] + " run in " + new Date());

15         Session session = sessionMap.get(Thread.currentThread());

16         if (session == null) {

17             session = sessionFactory.openSession();

18             sessionMap.put(Thread.currentThread(), session);

19         }

20         return session;

21     }

22     public static Session getCurrentSession() {

23         return sessionMap.get(Thread.currentThread());

24     }

25

26     public static void closeAndRemoveSession() {

27         System.out.println(Thread.currentThread().getStackTrace()[1]+ " run in " + new Date());//

28         Session session = sessionMap.remove(Thread.currentThread());

29         if (session != null) {

30             session.close();

31         }

32     }

33 } 
01 public class HibernateUtils {

02     private static Map<Thread, Session> sessionMap;

03     private static SessionFactory sessionFactory;

04     static {

05         sessionMap = new HashMap<Thread, Session>();

06         sessionFactory = new Configuration().configure().buildSessionFactory();

07     }

08

09     /**

10      * can only use in web filter, beause it should remove and clear resources

11      * @return

12      */

13     public static Session openSession() {

14         System.out.println(Thread.currentThread().getStackTrace()[1] + " run in " + new Date());

15         Session session = sessionMap.get(Thread.currentThread());

16         if (session == null) {

17             session = sessionFactory.openSession();

18             sessionMap.put(Thread.currentThread(), session);

19         }

20         return session;

21     }

22     public static Session getCurrentSession() {

23         return sessionMap.get(Thread.currentThread());

24     }

25

26     public static void closeAndRemoveSession() {

27         System.out.println(Thread.currentThread().getStackTrace()[1]+ " run in " + new Date());//

28         Session session = sessionMap.remove(Thread.currentThread());

29         if (session != null) {

30             session.close();

31         }

32     }

33 }

  hibernate整合进spring后的事务处理

  spring事物处理的方式有很多,详见:http://www.blogjava.net/robbie/archive/2009/04/05/264003.html

  介绍常用的:

  spring annotation声明式的事务管理

  事物处理层?

  比如保存一个User,可以在Service层和DAOImpl层实现:

01 public void save(User u) {

02     userDAO.save(u);

03 }

04

05 public void save(User u) {

06     System.out.println("save user from:" + this);

07     Session s = sessionFactory.openSession();

08     s.beginTransaction();

09     s.save(u);

10     s.getTransaction().commit();

11     s.close();

12 }

  假如我们还有个日志记录,没保存一个User对象,要写入日志进入数据库。

  而save(log) 和 save(user)必须处在同一事务中,所以不能放在DAOImpl层,事务处理在Service层。

   一般的事务处理

01 Session sess = factory.openSession();

02 Transaction tx;

03 try {

04     tx = sess.beginTransaction();

05     //do some work

06     //save(user);

07     //save(log);

08     ...

09     tx.commit();

10 } catch (Exception e) {

11     if (tx!=null) tx.rollback();

12     throw e;

13 } finally {

14     sess.close();

15 }

  并且要在实现层中的save()方法中也要加入事务处理,如果出出现异常要throws给上级处理!

  并且实现层中的session必须使用openCurrentSession()得到。

1 Session s = sessionFactory.getCurrentSession();

2 s.save(u);

   spring annotation事务处理

  Beans.xml中引入相应的xml命名空间和相应配置:

01 xmlns:tx="http://www.springframework.org/schema/tx"

02 http://www.springframework.org/schema/tx

03 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd

04 <tx:annotation-driven transaction-manager="txManager"/>

05 <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">

06   <property name="sessionFactory" ref="sessionFactory" />

07 </bean>

08 <bean id="dataSource"

09     class="org.apache.commons.dbcp.BasicDataSource"

10     destroy-method="close">

11     <property name="driverClassName"

12         value="${jdbc.driverClassName}" />

13     <property name="url" value="${jdbc.url}" />

14     <property name="username" value="${jdbc.username}" />

15     <property name="password" value="${jdbc.password}" />

16 </bean>

17 <bean id="sessionFactory"

18     class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

19     <property name="dataSource" ref="dataSource" />

20     <property name="annotatedClasses">

21         <list>

22             <value>com.syx.model.User</value>

23             <value>com.syx.model.Log</value>

24         </list>

25     </property>

26     <property name="hibernateProperties">

27         <props>

28             <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>

29             <prop key="hibernate.show_sql">true</prop>

30             <prop key="current_session_context_class">thread</prop>

31         </props>

32     </property>

33 </bean>

34 Save方法:

35 public void save(User u) {

36     Session s = sessionFactory.getCurrentSession();

37     s.save(u);

38 }

39 public void save(Log log) {

40     Session s = sessionFactory.getCurrentSession();

41     s.save(log);

42 }

43 Service层处理:

44 @Component("userService")

45 public class UserService {

46     UserDAO userDAO = null;

47     LogDAO logDAO = null;

48

49     public LogDAO getLogDAO() {

50         return logDAO;

51     }

52     @Resource(name="logDAOMySQLImpl")

53     public void setLogDAO(LogDAO logDAO) {

54         this.logDAO = logDAO;

55     }

56     @Transactional

57     public void save(User u) {

58         userDAO.save(u);

59         Log log = new Log();

60         log.setMsg(u.getName() + " saved in " + new Date());

61         logDAO.save(log);

62     }

63     public UserDAO getUserDAO() {

64         return userDAO;

65     }

66     @Resource(name="userDAOMySQLImpl")

67     public void setUserDAO(UserDAO userDAO) {

68         this.userDAO = userDAO;

69     }

70 }

  @Transactional详解

  什么时候rollback

  运行期异常,非运行期异常不会触发rollback

  必须uncheck (没有catch)

  不管什么异常,只要你catch了,spring就会放弃管理

  事务传播特性:propagation_required

  propagation 默认是 REQUIRED ,意思是有我们就用现成的,没的我们就创造一个,其他详细见文档

  spring xml声明式的事务管理

  配置环境和annotation版本一致,只是在用@Transactional处注释调用,在beans.xml中加入如下配置:

01 <!-- spring tranception xml config -->

02     <aop:config>

03         <aop:pointcut id="serviceOperation"

04             expression="execution(* com.syx.service..*.*(..))" />

05         <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" />

06     </aop:config>

07

08     <tx:advice id="txAdvice"  transaction-manager="txManager">

09         <tx:attributes>

10             <tx:method name="getUser" read-only="true" />

11             <tx:method name="save" /><!-- 相当于在上面切面pointcut@Transactional效果 -->

12         </tx:attributes>

13     </tx:advice>

  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回调:

1 return hibernateTemplate.executeWithNativeSession(

2     new HibernateCallback<List<T>>() {

3     public  List<T> doInHibernate(Session session)

4     throws HibernateException, SQLException {

5         return session.createQuery

6         ("FROM " + entityClass.getName() + " WHERE id IN (:ids)")//

7         .setParameterList("ids", idList).list();

8     }

  实际上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之类的操作了。

hibernate整合进spring后的事务处理的更多相关文章

  1. Spring第九篇【Spring与Hibernate整合】

    前言 前面已经学习了如何使用Spring与Struts2进行整合,本博文主要讲解如何使用Spring对Hibernate进行整合 Spring和Hibernate整合的关键点: SessionFact ...

  2. Hibernate【与Spring整合】

    前言 前面已经学习了如何使用Spring与Struts2进行整合,本博文主要讲解如何使用Spring对Hibernate进行整合 Spring和Hibernate整合的关键点: SessionFact ...

  3. 整合struts2+spring+hibernate

     一.准备struts2+spring+hibernate所须要的jar包:        新建web项目并将jar包引入到project项目中. 二.搭建struts2环境        a.在 ...

  4. 一 SSH整合:Spring整合Struts2的两种方式,struts.xml管理Action&Bean管理Action

    SSH回顾 1 引入jar包 Struts2的jar包 D:\Struts2\struts-2.3.35\apps\struts2-blank\WEB-INF\lib  开发基本包 Struts2有一 ...

  5. Spring与Hibernate整合中,使用OpenSessionInViewFilter后出现sessionFactory未注入问题

    近期在知乎看到一句话,保持学习的有一种是你看到了很多其它的牛人,不甘心,真的不甘心. Spring和hibernate整合的时候,jsp页面做展现,发现展现属性出现: org.apache.jaspe ...

  6. Struts+Spring+Hibernate整合入门详解

    Java 5.0 Struts 2.0.9 Spring 2.0.6 Hibernate 3.2.4 作者:  Liu Liu 转载请注明出处 基本概念和典型实用例子. 一.基本概念       St ...

  7. 框架篇:Spring+SpringMVC+hibernate整合开发

    前言: 最近闲的蛋疼,搭个框架写成博客记录下来,拉通一下之前所学知识,顺带装一下逼. 话不多说,我们直接步入正题. 准备工作: 1/ IntelliJIDEA的安装配置:jdk/tomcat等..(本 ...

  8. Java Web开发之Spring | SpringMvc | Mybatis | Hibernate整合、配置、使用

    1.Spring与Mybatis整合 web.xml: <?xml version="1.0" encoding="UTF-8"?> <web ...

  9. springmvc框架(Spring SpringMVC, Hibernate整合)

    直接干货 model 考虑给用户展示什么.关注支撑业务的信息构成.构建成模型. control 调用业务逻辑产生合适的数据以及传递数据给视图用于呈献: view怎样对数据进行布局,以一种优美的方式展示 ...

随机推荐

  1. Java常考面试题(二)

    序言 昨天刚开始的”每日5题面试“这类文章,感觉还不错,把一些平常看似懂了的东西,弄清楚了.就像什么是虚拟机?这个问题,看起来知道,但是要说出个所以然来,又懵逼了,经常回过头来看看做过的面试题,试着用 ...

  2. Vivado下生成及烧写MCS文件

    Jtag模式: 1.打开Open Hardware Manager 2. Tools ->Auto Connect 3.TCL输入: write_cfgmem -format MCS -size ...

  3. Python运维自动化开发之Fabric模块

    本章讲解fabric模块,与上一章的paramiko模块功能类似,fabric是在paramiko基础上又做了一层封装,操作起来更方便.主要用于多台服务器批量执行任务. 非内置Python模块,需要手 ...

  4. RightScale 2019年云状态报告:公共云快速增长 微软Azure增长最快

    https://www.rightscale.com/ 全球云管理服务厂商RightScale发布了年度云状态报告,今年报告的十大主要内容包括:企业在多云平台上投入巨资.公共云继续快速增长,但是私有云 ...

  5. angular学习笔记(三十)-指令(7)-compile和link(2)

    继续上一篇:angular学习笔记(三十)-指令(7)-compile和link(1) 上一篇讲了compile函数的基本概念,接下来详细讲解compile和link的执行顺序. 看一段三个指令嵌套的 ...

  6. Android 编程下 Canvas and Drawables

    Canvas and Drawables 安卓提供了一组绘制二维图形的 API(参考官方文档:Canvas and Drawables | Android Developers),这组 API 允许开 ...

  7. frame自适应

    <html> <head> <title>frame自适应</title> </head> <frameset rows=" ...

  8. 分析jvm线程堆栈

    目录 一.java线程状态 二.使用jstack生成进程dump文件 三.统计dump文件中处于不同状态的线程数量 四.举例分析不同状态的线程 1.分析BLOCKED (on object monit ...

  9. hdu3926(判断两个图是否相似,模版)

    题意:给你2个图,最大度为2.问两个图是否相似. 思路:图中有环.有链,判断环的个数以及每个环组成的人数,还有链的个数以及每个链组成的人数 是否相等即可. 如果形成了环,那么每形成一个环,结点数就会多 ...

  10. Java 11 将至,不妨了解一下 Oracle JDK 之外的版本

    Java 11 计划于本月,即 9 月 25 日发布.与 Java 10 不同,Java 11 不仅提供了长期支持,还将作为 Java 平台的参考实现.新的长期支持版本每三年发布一次,根据后续的发布计 ...