峰Spring4学习(8)spring对事务的支持
一、事务简介:

二、编程式事务管理:

例子
1、需求:模拟转账,张三向李四转账50元;
数据库中存在t_count表:

代码实现:
BankDao.java:
package com.cy.dao;
public interface BankDao {
//转入money元
public void inMoney(int money,int userId);
//转出money元
public void outMoney(int money,int userId);
}
BankDaoImpl.java:
package com.cy.dao.impl; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import com.cy.dao.BankDao; public class BankDaoImpl implements BankDao { private NamedParameterJdbcTemplate namedParameterJdbcTemplate; public void setNamedParameterJdbcTemplate(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
} //userId转入money元
@Override
public void inMoney(int money, int userId) {
String sql = "update t_count set count = count + :money where userId = :userId";
MapSqlParameterSource sps = new MapSqlParameterSource();
sps.addValue("money", money)
.addValue("userId", userId);
namedParameterJdbcTemplate.update(sql, sps);
} //userId转出money元
@Override
public void outMoney(int money, int userId) {
String sql = "update t_count set count = count - :money where userId = :userId";
MapSqlParameterSource sps = new MapSqlParameterSource();
sps.addValue("money", money)
.addValue("userId", userId);
namedParameterJdbcTemplate.update(sql, sps);
} }
BankService.java:
package com.cy.service;
public interface BankService {
/**
* A向B转账count元
* @param count
* @param userIdA
* @param userIdB
*/
public void transferAccounts(int count, int userIdA, int userIdB);
}
BankServiceImpl.java:
package com.cy.service.impl; import com.cy.dao.BankDao;
import com.cy.service.BankService; public class BankServiceImpl implements BankService { private BankDao bankDao; public void setBankDao(BankDao bankDao) {
this.bankDao = bankDao;
} //A向B转账count元
@Override
public void transferAccounts(int count, int userIdA, int userIdB) {
bankDao.outMoney(count, userIdA);
bankDao.inMoney(count, userIdB);
} }
beans.xml配置:
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean> <context:property-placeholder location="jdbc.properties"/> <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"></constructor-arg>
</bean> <bean id="bankDao" class="com.cy.dao.impl.BankDaoImpl">
<property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"></property>
</bean> <bean id="bankService" class="com.cy.service.impl.BankServiceImpl">
<property name="bankDao" ref="bankDao"></property>
</bean> </beans>
测试代码:
package com.cy.test; import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.cy.service.BankService; public class T {
private ApplicationContext ac; @Before
public void setUp() throws Exception {
ac=new ClassPathXmlApplicationContext("beans.xml");
} //测试代码
@Test
public void transferAccounts() {
BankService bankService = (BankService)ac.getBean("bankService");
bankService.transferAccounts(50, 1, 2);
} }
将上面代码修改为如下:
1)BankDaoImpl.java中构建t_count2不存在,无法完成转入,会抛出异常:
//userId转入money元
@Override
public void inMoney(int money, int userId) {
String sql = "update t_count2 set count = count + :money where userId = :userId";
MapSqlParameterSource sps = new MapSqlParameterSource();
sps.addValue("money", money)
.addValue("userId", userId);
namedParameterJdbcTemplate.update(sql, sps);
}
2)BankServiceImpl.java中使用编程式事务管理:
package com.cy.service.impl; import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate; import com.cy.dao.BankDao;
import com.cy.service.BankService; public class BankServiceImpl implements BankService { private BankDao bankDao; private TransactionTemplate transactionTemplate; public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
} public void setBankDao(BankDao bankDao) {
this.bankDao = bankDao;
} //A向B转账count元
@Override
public void transferAccounts(final int count, final int userIdA, final int userIdB) {
transactionTemplate.execute(new TransactionCallbackWithoutResult(){ @Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
bankDao.outMoney(count, userIdA);
bankDao.inMoney(count, userIdB);
}
});
} }
3)beans.xml中配置jdbc事务管理器、transactionTemplate:
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean> <context:property-placeholder location="jdbc.properties"/> <!-- jdbc事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean> <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"></constructor-arg>
</bean> <bean id="bankDao" class="com.cy.dao.impl.BankDaoImpl">
<property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"></property>
</bean> <bean id="bankService" class="com.cy.service.impl.BankServiceImpl">
<property name="bankDao" ref="bankDao"></property>
<property name="transactionTemplate" ref="transactionTemplate"></property>
</bean> </beans>
运行测试程序,报错,但是张三账户中仍然是500元,李四账户中没有收到钱,为500元。事务进行了回滚。
三、声明式事务管理:

1.使用xml配置声明式事务:
BankServiceImpl.java:
package com.cy.service.impl; import com.cy.dao.BankDao;
import com.cy.service.BankService; public class BankServiceImpl implements BankService { private BankDao bankDao; public void setBankDao(BankDao bankDao) {
this.bankDao = bankDao;
} //A向B转账count元
@Override
public void transferAccounts(final int count, final int userIdA, final int userIdB) {
bankDao.outMoney(count, userIdA);
bankDao.inMoney(count, userIdB);
} }
beans.xml:
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean> <context:property-placeholder location="jdbc.properties"/> <!-- jdbc事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean> <!-- 配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice> <!-- 配置事务切面 -->
<aop:config>
<!-- 配置切点 -->
<aop:pointcut id="serviceMethod" expression="execution(* com.cy.service.*.*(..))" />
<!-- 配置事务通知 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod"/>
</aop:config> <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"></constructor-arg>
</bean> <bean id="bankDao" class="com.cy.dao.impl.BankDaoImpl">
<property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"></property>
</bean> <bean id="bankService" class="com.cy.service.impl.BankServiceImpl">
<property name="bankDao" ref="bankDao"></property>
</bean> </beans>
运行测试代码,事务得到回滚。
2.使用注解配置声明式事务:
BankServiceImpl.java:
package com.cy.service.impl; import org.springframework.transaction.annotation.Transactional; import com.cy.dao.BankDao;
import com.cy.service.BankService; @Transactional
public class BankServiceImpl implements BankService { private BankDao bankDao; public void setBankDao(BankDao bankDao) {
this.bankDao = bankDao;
} //A向B转账count元
@Override
public void transferAccounts(final int count, final int userIdA, final int userIdB) {
bankDao.outMoney(count, userIdA);
bankDao.inMoney(count, userIdB);
} }
beans.xml配置:
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean> <context:property-placeholder location="jdbc.properties"/> <!-- jdbc事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean> <tx:annotation-driven transaction-manager="transactionManager"/> <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"></constructor-arg>
</bean> <bean id="bankDao" class="com.cy.dao.impl.BankDaoImpl">
<property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"></property>
</bean> <bean id="bankService" class="com.cy.service.impl.BankServiceImpl">
<property name="bankDao" ref="bankDao"></property>
</bean> </beans>
四、事务的传播行为:


read-only:只读的;
例如将上面xml中的事务通知修改为配置如下:
beans.xml:
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean> <context:property-placeholder location="jdbc.properties"/> <!-- jdbc事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean> <!-- 配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="edit*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="new*" propagation="REQUIRED" />
<tx:method name="set*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="change*" propagation="REQUIRED" />
<tx:method name="get*" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" propagation="REQUIRED" read-only="true" />
<tx:method name="load*" propagation="REQUIRED" read-only="true" />
<tx:method name="transferAccounts" propagation="REQUIRED" />
<tx:method name="*" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice> <!-- 配置事务切面 -->
<aop:config>
<!-- 配置切点 -->
<aop:pointcut id="serviceMethod" expression="execution(* com.cy.service.*.*(..))" />
<!-- 配置事务通知 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod"/>
</aop:config> <bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"></constructor-arg>
</bean> <bean id="bankDao" class="com.cy.dao.impl.BankDaoImpl">
<property name="namedParameterJdbcTemplate" ref="namedParameterJdbcTemplate"></property>
</bean> <bean id="bankService" class="com.cy.service.impl.BankServiceImpl">
<property name="bankDao" ref="bankDao"></property>
</bean> </beans>
-----------------------------
峰Spring4学习(8)spring对事务的支持的更多相关文章
- 【spring源码学习】spring的事务管理的源码解析
[一]spring事务管理(1)spring的事务管理,是基于aop动态代理实现的.对目标对象生成代理对象,加入事务管理的核心拦截器==>org.springframework.transact ...
- Spring(九)Spring对事务的支持
一.对事务的支持 事务:是一组原子操作的工作单元,要么全部成功,要么全部失败 Spring管理事务方式: JDBC编程事务管理:--可以控制到代码中的行 可以清楚的控制事务的边界,事务控制粒度化细(编 ...
- 峰Spring4学习(4)spring自动装配
一.自动装配: Model类: People.java: package com.cy.entity; public class People { private int id; private St ...
- 峰Spring4学习(6)spring AOP的应用例子
一.AOP简介: 二.AOP实例: 三.使用的例子 需求:在student添加的前后,打印日志信息: 0)spring AOP需要引用的jar包: 1)StudentService.java接口: p ...
- 峰Spring4学习(7)spring对JDBC的支持
第一节: 工程结构: 1)student.java: package com.cy.model; public class Student { private int id; private Stri ...
- spring4 学习4 spring MVC+mybatis+Mysql
在前面搭建的基础上,引入新的jar包如下: aopalliance-1.0.jaraspectjweaver-1.8.8.jarmybatis-3.3.0.jarmybatis-spring-1.2. ...
- 峰Spring4学习(5)bean之间的关系和bean的作用范围
一.bean之间的关系: 1)继承: People.java实体类: package com.cy.entity; public class People { private int id; priv ...
- 峰Spring4学习(3)注入参数的几种类型
People.java model类: package com.cy.entity; import java.util.ArrayList; import java.util.HashMap; im ...
- 峰Spring4学习(2)依赖注入的几种方式
一.装配一个bean 二.依赖注入的几种方式 com.cy.entity People.java: package com.cy.entity; public class People { pri ...
随机推荐
- 如何在 OSX 中使用多个JDK版本
升级macbook小白的硬盘成SSD后,重新安装了系统和JDK8,但是启动eclipse还是报告需要安装JDK6,于是也按照提示安装了Apple JDK6,这导致系统中有两个JDK,一个是Oracle ...
- git squash 和 git rebase
In git, what is the difference between merge --squash and rebase? 上面链接的回答中的总结: Both git merge --squa ...
- 【图片服务器】搭建Nginx图片服务器
一.安装Nginx 二.安装vsftpd 三.开始搭建Nginx图片服务器 1.效果 例如:图片通过ftp服务上传到/home/ftpuser/www/images目录下,我想通过访问Nginx服务器 ...
- JS中innerHTML和innerText,outerHTML和outerText
innerHTML 声明了元素含有的HTML文本,不包括元素本身的开始标记和结束标记 innerHTML是符合W3C标准的属性,而innerText只适用于IE浏览器(现在也适应chrome浏览器 ...
- pix2pix-tensorflow搭建及其使用
目录 pix2pix-tensorflow搭建过程 1. 环境搭建 2. 环境说明 3. 开始搭建 4. 训练结果说明 5. 数据集 5.1 图片格式说明 5.3 从先用图片创建图像对 5.4 如何进 ...
- adb相关指令
adb rootadb connect 172.16.20.162 //通过adb连接远程设备adb pull /data/data/com.xiaomi.voicecontrol /Users/r ...
- Angular单元测试
https://angular.github.io/protractor/#/http://jasmine.github.io/2.4/introduction.html 测试程序有两种主要方法:端对 ...
- python2和python3的区别——持续更新
1.在 cookbook 上看到的,python3支持 *运算符 来接收迭代变量,如: a, *b = [, , , ] python2是不支持的! 2.在 cookbook 上看到的,python3 ...
- sql语句in
在今天之前sql一直用in语句,知道今天遇到一张数据量很大的表查了三分钟才查出来,这才意识到数据库优化有多重要.作为一名开发人员,首先从优化sql语句开始. 之前用in写sql是这样的 select ...
- HDU 2553 状态压缩
N皇后问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...