一、事务简介:

二、编程式事务管理:

例子

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);
} }
 
2、上面程序运行是没问题的,张三向李四转50元,张三账户为450元,李四账户为550元。
模拟一种异常情况:
inMoney中将t_count改为t_count2,这张表不存在,张三转出50元,李四没有收到。这时需要事务回滚;

将上面代码修改为如下:

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元。事务进行了回滚。

三、声明式事务管理:

上面编程式事务管理的缺点:
非业务代码已经嵌入到业务代码里面,转账的业务代码就两句。控制事务的代码和业务代码混在一起,不太好。
 
声明式事务管理:
使用spring的AOP,面向切面,把事务切进去;

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对事务的支持的更多相关文章

  1. 【spring源码学习】spring的事务管理的源码解析

    [一]spring事务管理(1)spring的事务管理,是基于aop动态代理实现的.对目标对象生成代理对象,加入事务管理的核心拦截器==>org.springframework.transact ...

  2. Spring(九)Spring对事务的支持

    一.对事务的支持 事务:是一组原子操作的工作单元,要么全部成功,要么全部失败 Spring管理事务方式: JDBC编程事务管理:--可以控制到代码中的行 可以清楚的控制事务的边界,事务控制粒度化细(编 ...

  3. 峰Spring4学习(4)spring自动装配

    一.自动装配: Model类: People.java: package com.cy.entity; public class People { private int id; private St ...

  4. 峰Spring4学习(6)spring AOP的应用例子

    一.AOP简介: 二.AOP实例: 三.使用的例子 需求:在student添加的前后,打印日志信息: 0)spring AOP需要引用的jar包: 1)StudentService.java接口: p ...

  5. 峰Spring4学习(7)spring对JDBC的支持

    第一节: 工程结构: 1)student.java: package com.cy.model; public class Student { private int id; private Stri ...

  6. spring4 学习4 spring MVC+mybatis+Mysql

    在前面搭建的基础上,引入新的jar包如下: aopalliance-1.0.jaraspectjweaver-1.8.8.jarmybatis-3.3.0.jarmybatis-spring-1.2. ...

  7. 峰Spring4学习(5)bean之间的关系和bean的作用范围

    一.bean之间的关系: 1)继承: People.java实体类: package com.cy.entity; public class People { private int id; priv ...

  8. 峰Spring4学习(3)注入参数的几种类型

    People.java  model类: package com.cy.entity; import java.util.ArrayList; import java.util.HashMap; im ...

  9. 峰Spring4学习(2)依赖注入的几种方式

    一.装配一个bean 二.依赖注入的几种方式 com.cy.entity   People.java: package com.cy.entity; public class People { pri ...

随机推荐

  1. Maven编译的时候加载本地路径jar

    大家都知道Maven的依赖是通过pom文件管理的,只要配置了<dependency>,Maven就会从本地仓库 -> 远程仓库 -> 中央仓库获取依赖的jar. 但是如果仓库中 ...

  2. 【eclipse】运行maven项目clean tomcat7:run报错

    问题: Failed to execute goal org.apache.maven.plugins:maven-clean-plugin:2.5:clean 解决: 关闭进程javaw.exe,然 ...

  3. [转] VR-FORCES 介绍

    转自:https://sanwen8.cn/p/1e6GQeK.html 今天给各位介绍的仿真平台是VR-Forces.VR-Forces是新加坡公司MAK的产品,前身是美国公司.在仿真平台领域里面, ...

  4. JavaScript权威指南--window对象

    知识要点 window对象及其客户端javascript所扮演的核心角色:它是客户端javascript程序的全局对象.本章介绍window对象的属性和方法,这些属性定义了不同的API,但是只有一部分 ...

  5. JAVA异常处理分析高级进界(下)

    既然Throwable是异常处理机制的核心,那么,我们就来分析下它的源码来看看它是如何实现的. 进行分析前,我们可以先想想如果让我们实现一个异常处理机制,我们需要它做什么? 1. 发生异常终止程序执行 ...

  6. c# winform 操作oracle数据库的Blob字段,把图片存储到数据库,保存图片到数据库

    ///c# winform 操作oracle数据库的Blob字段,把图片存储到数据库,保存图片到数据库 闲话不多说,直接上代码 using System; using System.Collectio ...

  7. 转载-LVS的三种工作模式

    来源地址:http://www.uml.org.cn/zjjs/201211124.asp 1.lvs简介         lvs是一个开源的软件,由毕业于国防科技大学的章文嵩博士于1998年5月创立 ...

  8. L202

    Yuan Cao’s teenage years were hardly typical. By age 18, he had already graduated from high school, ...

  9. L177 Arctic ice brings an understanding of ancient Europe’s economy

    Greenland's icy mountains are not an obvious place to search for an archive of economic history, but ...

  10. [Tomcat无法启动]'Starting Tomcat v8.0 Server at localhost' has encountered a problem.

    运行一个index.jsp,运行提示如下错误:点击服务器 解决办法1: 点击Tomcat服务器,将服务器里的web工程删除掉,再重新运行index.jsp. 解决办法2: 关闭Tomcat,最简单的方 ...