Java Spring-事务管理
2017-11-12 16:31:59
Spring的事务管理分为两种:
- 编程式的事务管理:手动编写代码
- 声明式的事务管理:只需要配置就可以
一、最初的环境搭建
public interface AccountDAO {public void out(String to,Double money);public void in(String from, Double money);
}public class AccountDAOImpl extends JdbcDaoSupport implements AccountDAO {@Overridepublic void out(String from, Double money) {String sql = "update account set money = money - ? where name = ?";this.getJdbcTemplate().update(sql, money,from);}@Overridepublic void in(String to, Double money) {String sql = "update account set money = money + ? where name = ?";this.getJdbcTemplate().update(sql, money , to);}
}public interface AccountService {public void transfer(String from, String to, Double money);
}public class AccountServiceImpl implements AccountService {@Resource(name = "accountDao")private AccountDAO accountDAO;@Overridepublic void transfer(String from, String to, Double money) {accountDAO.out(from,money);accountDAO.in(to,money);}
}// 测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:config4.xml")
public class TestDemo {@Resource(name = "accountservice")private AccountService accountService;@Testpublic void demo(){accountService.transfer("aaa","bbb",100d);}
}
二、手动式的事务管理
可以发现,在没有引入事务管理的时候,如果在转账的out和in之间出现了异常,那么就会导致转账的结果出错。所以我们需要引入事务管理技术。
Spring提供了事务管理的模板(工具类),可以方便我们对事务进行管理。
具体步骤:
- 第一步:注册事务管理器
- 第二步:注册事务模板类
- 第三步:在业务层注入模板类
- 第四步:在业务层代码上使用模板
public class AccountServiceImpl implements AccountService {@Resource(name = "accountDao")private AccountDAO accountDAO;@Resource(name = "transactionTemplate")private TransactionTemplate transactionTemplate;@Overridepublic void transfer(String from, String to, Double money) {transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {accountDAO.out(from,money);accountDAO.in(to,money);}});}
}
XML的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--配置连接池--><!--<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">--><!--<property name="driverClassName" value="com.mysql.jdbc.Driver"/>--><!--<property name="url" value="jdbc:mysql://localhost:3306/testdb"/>--><!--<property name="username" value="host"/>--><!--<property name="password" value="hy1102"/>--><!--</bean>--><!-- 配置DBCP连接池 --><!--<bean id="datasource" class=" org.apache.commons.dbcp.BasicDataSource ">--><!--<property name="driverClassName" value="com.mysql.jdbc.Driver"/>--><!--<property name="url" value="jdbc:mysql://localhost:3306/testdb"/>--><!--<property name="username" value="host"/>--><!--<property name="password" value="hy1102"/>--><!--</bean>--><!-- 引入该属性文件 --><!--<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">--><!--<property name="location" value="classpath:jdbc.properties"/>--><!--</bean>--><!-- 使用 context 标签引入属性文件 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置 c3p0 连接池 --><bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driver}"/><property name="jdbcUrl" value="${jdbc.url}"/><property name="user" value="${jdbc.user}"/><property name="password" value="${jdbc.password}"/></bean><!-- 定义模板 --><bean id="jdbctemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="datasource"/></bean><bean id="userdao" class="spring3.UserDao"><property name="jdbcTemplate" ref="jdbctemplate"/></bean><!--业务层--><bean id="accountservice" class="spring4.AccountServiceImpl"/><!--持久层--><bean id="accountDao" class="spring4.AccountDAOImpl"><!--事实上可以直接注入连接池来创建模板--><property name="dataSource" ref="datasource"/></bean><!--配置事务管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!-- 需要注入连接池,通过连接池获得连接 --><property name="dataSource" ref="datasource"/></bean><!-- 事务管理的模板 --><bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"><property name="transactionManager" ref="transactionManager"/></bean></beans>
三、声明式的事务管理
手动编码方式类似于对transfer方法进行增强,所以考虑代理Service对象。
- 基于原始的TransactionProxyFactoryBean
// 业务代码
public class AccountServiceImpl implements AccountService {@Resource(name = "accountDao")private AccountDAO accountDAO;@Overridepublic void transfer(String from, String to, Double money) {accountDAO.out(from,money);accountDAO.in(to,money);}
}// 测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:config4.xml")
public class TestDemo {@Resource(name = "accountServiceProxy")private AccountService accountService;@Testpublic void demo(){accountService.transfer("aaa","bbb",100d);}
}
XML的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--配置连接池--><!--<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">--><!--<property name="driverClassName" value="com.mysql.jdbc.Driver"/>--><!--<property name="url" value="jdbc:mysql://localhost:3306/testdb"/>--><!--<property name="username" value="host"/>--><!--<property name="password" value="hy1102"/>--><!--</bean>--><!-- 配置DBCP连接池 --><!--<bean id="datasource" class=" org.apache.commons.dbcp.BasicDataSource ">--><!--<property name="driverClassName" value="com.mysql.jdbc.Driver"/>--><!--<property name="url" value="jdbc:mysql://localhost:3306/testdb"/>--><!--<property name="username" value="host"/>--><!--<property name="password" value="hy1102"/>--><!--</bean>--><!-- 引入该属性文件 --><!--<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">--><!--<property name="location" value="classpath:jdbc.properties"/>--><!--</bean>--><!-- 使用 context 标签引入属性文件 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置 c3p0 连接池 --><bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driver}"/><property name="jdbcUrl" value="${jdbc.url}"/><property name="user" value="${jdbc.user}"/><property name="password" value="${jdbc.password}"/></bean><!-- 定义模板 --><bean id="jdbctemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="datasource"/></bean><bean id="userdao" class="spring3.UserDao"><property name="jdbcTemplate" ref="jdbctemplate"/></bean><!--业务层--><bean id="accountservice" class="spring4.AccountServiceImpl"/><!--持久层--><bean id="accountDao" class="spring4.AccountDAOImpl"><!--事实上可以直接注入连接池来创建模板--><property name="dataSource" ref="datasource"/></bean><!--配置事务管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!-- 需要注入连接池,通过连接池获得连接 --><property name="dataSource" ref="datasource"/></bean><!-- 事务管理的模板 --><bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"><property name="transactionManager" ref="transactionManager"/></bean><!-- 配置生成代理对象 --><bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><!-- 目标对象 --><property name="target" ref="accountservice"/><!-- 注入事务管理器 --><property name="transactionManager" ref="transactionManager"/><!-- 事务的属性设置 --><property name="transactionAttributes"><props><prop key="transfer">PROPAGATION_REQUIRED</prop></props></property></bean></beans>
prop格式:PROPAGATION,ISOLATION,readOnly,-Exception,+Exception
* 顺序:传播行为、隔离级别、事务是否只读、发生哪些异常可以回滚事务(所有的异常都回滚)、发生了哪些异常不回
滚
<prop key="transfer">PROPAGATION_REQUIRED,readonly</prop>
<prop key="transfer">PROPAGATION_REQUIRED,+java.lang.ArithmeticException</prop>
- 基于切面自动代理
上面的方法每次都要手动生成代理,显然是不太合适的,所以可以使用基于切面的自动代理。
public interface AccountDAO {public void out(String to,Double money);public void in(String from, Double money);
}public class AccountDAOImpl extends JdbcDaoSupport implements AccountDAO {@Overridepublic void out(String from, Double money) {String sql = "update account set money = money - ? where name = ?";this.getJdbcTemplate().update(sql, money,from);}@Overridepublic void in(String to, Double money) {String sql = "update account set money = money + ? where name = ?";this.getJdbcTemplate().update(sql, money , to);}
}public interface AccountService {public void transfer(String from, String to, Double money);
}public class AccountServiceImpl implements AccountService {@Resource(name = "accountDao")private AccountDAO accountDAO;@Overridepublic void transfer(String from, String to, Double money) {accountDAO.out(from,money);accountDAO.in(to,money);}
}//测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:config5.xml")
public class TestDemo {@Resource(name = "accountservice")private AccountService accountService;@Testpublic void demo(){accountService.transfer("aaa","bbb",100d);}
}
XML的配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop" xmlns="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 使用 context 标签引入属性文件 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置 c3p0 连接池 --><bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driver}"/><property name="jdbcUrl" value="${jdbc.url}"/><property name="user" value="${jdbc.user}"/><property name="password" value="${jdbc.password}"/></bean><!-- 定义模板 --><bean id="jdbctemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="datasource"/></bean><bean id="userdao" class="spring3.UserDao"><property name="jdbcTemplate" ref="jdbctemplate"/></bean><!--业务层--><bean id="accountservice" class="spring4.AccountServiceImpl"/><!--持久层--><bean id="accountDao" class="spring4.AccountDAOImpl"><!--事实上可以直接注入连接池来创建模板--><property name="dataSource" ref="datasource"/></bean><!--配置事务管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!-- 需要注入连接池,通过连接池获得连接 --><property name="dataSource" ref="datasource"/></bean><!-- 定义一个增强 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><!-- 增强(事务)的属性的配置 --><tx:attributes><!--isolation:DEFAULT :事务的隔离级别.propagation :事务的传播行为.read-only :false.不是只读timeout :-1no-rollback-for :发生哪些异常不回滚rollback-for :发生哪些异常回滚事务--><tx:method name="transfer" isolation="DEFAULT"/></tx:attributes></tx:advice><!-- aop配置定义切面和切点的信息 --><aop:config><!-- 定义切点:哪些类的哪些方法应用增强 --><aop:pointcut expression=" execution(* spring4.AccountService+.*(..)) " id="mypointcut"/><!-- 定义切面: --><aop:advisor advice-ref="txAdvice" pointcut-ref="mypointcut"/></aop:config></beans>
- 基于注解的事务配置
具体步骤:
- 第一步:事务管理器
- 第二步:注解事务
- 第三步:在Service上使用注解
* 注解中有属性值:
* isolation
* propagation
* readOnly
...
- 第四步:测试
@Transactional
public class AccountServiceImpl implements AccountService {@Resource(name = "accountDao")private AccountDAO accountDAO;@Overridepublic void transfer(String from, String to, Double money) {accountDAO.out(from,money);// int i = 1/0;accountDAO.in(to,money);}
}
XML配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop" xmlns="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 使用 context 标签引入属性文件 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置 c3p0 连接池 --><bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driver}"/><property name="jdbcUrl" value="${jdbc.url}"/><property name="user" value="${jdbc.user}"/><property name="password" value="${jdbc.password}"/></bean><!-- 定义模板 --><bean id="jdbctemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="datasource"/></bean><bean id="userdao" class="spring3.UserDao"><property name="jdbcTemplate" ref="jdbctemplate"/></bean><!--业务层--><bean id="accountservice" class="spring4.AccountServiceImpl"/><!--持久层--><bean id="accountDao" class="spring4.AccountDAOImpl"><!--事实上可以直接注入连接池来创建模板--><property name="dataSource" ref="datasource"/></bean><!--配置事务管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!-- 需要注入连接池,通过连接池获得连接 --><property name="dataSource" ref="datasource"/></bean><tx:annotation-driven transaction-manager="transactionManager"/></beans>
比较来看,最后的基于注解的方式是最容易,也是代码量最少的。
转载于:https://www.cnblogs.com/TIMHY/p/7822391.html
Java Spring-事务管理相关推荐
- JAVA Spring 事务管理事务不回滚问题
Spring事务管理事务不回滚 dao层: @Repository public class UserDaoImpl implements UserDao { @Autowired private J ...
- java中事务实例,Java Spring 事务管理器入门例子教程(TranscationManager)
注:阅读本文之前请务必有上文的基础 本文我们使用的事务管理器(TranscationManager)的作用是保证一组数据库操作的原子性.保证在操作时,如果出现异常,事务管理器会将状态恢复到进行本组操作 ...
- Java Spring 事务管理
包spring-tx-xxx.jar xml配置 <!-- 配置通知,tx:attributes配置传播行为和隔离级别--> <tx:advice id="txAdvice ...
- Spring事务管理 与 SpringAOP
1,Spring事务的核心接口 Spring事务管理的实现有许多细节,如果对整个接口框架有个大体了解会非常有利于我们理解事务,下面通过讲解Spring的事务接口来了解Spring实现事务的具体策略. ...
- Spring 事务管理高级应用难点剖析
Spring 事务管理高级应用难点剖析: 第 1 部分 http://www.ibm.com/developerworks/cn/java/j-lo-spring-ts1/index.html htt ...
- Spring 事务管理高级应用难点剖析--转
第 1 部分 http://www.ibm.com/search/csass/search/?q=%E4%BA%8B%E5%8A%A1&sn=dw&lang=zh&cc=CN& ...
- Spring事务管理(详解+实例)
写这篇博客之前我首先读了<Spring in action>,之后在网上看了一些关于Spring事务管理的文章,感觉都没有讲全,这里就将书上的和网上关于事务的知识总结一下,参考的文章如下: ...
- springaop事务逻辑原理_架构师:一篇文章掌握——Spring 事务管理
对大多数Java开发者来说,Spring事务管理是Spring应用中最常用的功能,使用也比较简单.本文主要逐步介绍Spring事务管理的相关知识点及原理,作为Spring事务管理的学习总结. 一.关键 ...
- Spring事务管理详解_基本原理_事务管理方式
Spring事务管理详解_基本原理_事务管理方式 1. 事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,使用JDBC的事务管理机制,就是利用java.sql.Connection对象 ...
- Spring jdbc Template和Spring 事务管理
使用jdbcTemplate完成增删改查操作(重点) package com.it.jdbctemplate;import java.util.List;import org.junit.Test; ...
最新文章
- 地图收敛心得170405
- C++关键字static
- mybatis中使用XML配置文件方式实现CRUD模板流程
- SpringBoot 文件上传、下载、设置大小
- 《SuperMap GIS二次开发MVC实战训练---江海区慢性病防治院系统》项目研发阶段性总结
- css 相对定位与绝对定位
- vueCli3中使用代理,点击页面的刷新按钮时报错
- MySQL深度剖析之事务隔离级别和锁机制(2021)
- Android APK反编译详解
- [JDBC] MySQL中数据的增查删改(二)
- PAT(乙级)1016
- vue - 开发环境构建
- java编译系统找不到指定路径_为什么我在E盘安装了java,命令指示符输入后却提示系统找不到指定路径?...
- 各类编程开发软件及资源全版本下载地址合集
- python爬虫获取城市天气信息
- day18-正则表达式
- python显示gif图片报错_4种方法(plglet、tkinter、guizero、pygame)的GUI中显示gif
- mongodb ubuntu下安装以及开启远程访问
- matplotlib-04 xlabel设置x轴的标签
- 访问者模式(JAVA)
热门文章
- java 数字千分位_java实现数字千分位的显示
- php和数据库的永久链接,php – WordPress永久链接,包括名称和ID,但仅考虑ID
- pandas mysql insert_python – Pandas将数据插入MySQL
- 医疗知识图谱NLP项目,实体规模4.4万,实体关系规模30万
- python again语句_【python笔记 二 】python语句
- android hook 模拟点击_手把手讲解 Android Hook-实现无清单启动Activity
- python3生成随机数_python3实现随机数
- 照片浏览器_照片审核不通过!这可能是史上最亏的中级失败理由!
- 程序员如何掌握计算机英语
- python语法中的网络编程_(六)python语法之网络编程