一、编程式事务简介
在 Spring 出现以前,编程式事务管理对基于 POJO 的应用来说是唯一选择。用过 Hibernate 的人都知道,我们需要在代码中显式调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。通过 Spring 提供的事务管理 API,我们可以在代码中灵活控制事务的执行。在底层,Spring 仍然将事务操作委托给底层的持久化框架来执行。
二、实例分析
2.1,首先,导入Spring、Hibernate的相关jar包,以及所使用数据库的驱动jar,搭建其基本环境
2.2,其次,编写相关代码
ApplicationContext配置文件:
<pre name="code" class="html"><?xml version="1.0" encoding="UTF-8"?> <beans xmlns="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/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <!-- 注入D层实现 --> <bean id="logManagerImpl" class="com.angel.usermanager.manager.LogManagerImpl"></bean> <bean id="userManagerImpl" class="com.angel.usermanager.manager.UserManagerImpl"> <property name="logManager" ref="logManagerImpl"></property> <property name="log" ref="logModel"></property> </bean> <!-- 注入实体 --> <bean id="userModel" class="com.angel.usermanager.domain.User"></bean> <bean id="logModel" class="com.angel.usermanager.domain.Log"></bean> </beans>
在Hibernate的配置文件中添加:
<span style="font-family:KaiTi_GB2312;font-size:18px;"><property name="hibernate.current_session_context_class">thread</property></span>注意:
* 如果是本地事务(jdbc事务)
<property name="hibernate.current_session_context_class">thread</property>
* 如果是全局事务(jta事务)
<property name="hibernate.current_session_context_class">jta</property>
HibernateUtils类:
<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.angel.usermanager.util; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtils { private static SessionFactory factory; private HibernateUtils() { } static { try { Configuration cfg = new Configuration().configure(); factory = cfg.buildSessionFactory(); }catch(Exception e) { e.printStackTrace(); throw new java.lang.RuntimeException(e); } } public static SessionFactory getSessionFactory() { return factory; } public static Session getSession() { return factory.openSession(); } public static void closeSession(Session session) { if (session != null) { if (session.isOpen()) { session.close(); } } } } </span>
</pre><pre name="code" class="java">package com.angel.usermanager.manager; import java.util.Date; import org.hibernate.Session; import com.angel.usermanager.domain.Log; import com.angel.usermanager.domain.User; import com.angel.usermanager.util.HibernateUtils; public class UserManagerImpl implements UserManager { private LogManager logManager; public void setLogManager(LogManager logManager) { this.logManager = logManager; } private Log log; public void setLog(Log log){ this.log=log; } public void addUser(User user) { Session session = null; try { <span style="color:#ff6666;">session = HibernateUtils.getSessionFactory().getCurrentSession();</span> session.beginTransaction(); session.save(user); log.setType("操作日志"); log.setTime(new Date()); log.setDetail("Agel7"); logManager.addLog(log); session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); session.getTransaction().rollback(); } } }
测试类:
<pre name="code" class="java">package com.angel.usermanager.test; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.angel.usermanager.domain.User; import com.angel.usermanager.manager.UserManager; public class Client { public static void main(String[] args) { // 读取配置文件 BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml"); UserManager userManager = (UserManager) factory.getBean("userManagerImpl"); User user = (User) factory.getBean("userModel"); user.setName("张三7"); userManager.addUser(user); } }
三、总结
openSession和getCurrentSession的区别:openSession必须手动关闭,currentSession在事务结束后自动关闭;openSession没有和当前线程绑定,currentSession和当前线程绑定
采用编程式事务,方便了我们对于事务的理解。但是,事务管理的代码散落在业务逻辑代码中,破坏了原有代码的条理性,并且每一个业务方法都包含了类似的启动事务、提交/回滚事务的样板代码。这就导致了相同代码的反复出现,有没有什么解决方案呢?第一,spring提供了简化方法,在数据访问层非常常见的模板回调模式。第二,声明式事务