转:Spring中事物管理
1.什么是事务?
事务是逻辑上的一组操作,这组操作要么全部成功,要么全部失败
2.事物具有四大特性ACID
原子性:(atomicity)
原子性指的是事务是一个不可分割的工作单位,事务中的操作要么全部发生,要么都不发生
(就像物理中,原子是最小不可分割的单位)
一致性:(consistency)
一致性指的是事务前后数据的完整性必须保持一致(比如说,转账:张三账户有2000元,李四账户有2000元,一共4000元
张三项李四转账2000元后,一共还是4000元)
事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的
隔离性:(isolation)
隔离性指的是多个用户并发访问数据库是,一个用户的事务不能被其他用户的事务
干扰,多个并发事务之间相互隔离
持久性:(durability)。
持久性指的是一个事务一旦被提交,他对数据库中的数据的改变是永久的,即使数据库故障
也不应该对其有任何影响
3.Spring中事务的管理
主要用于事务的提交,回滚等说明
TransactionDefintion 事务定义信息(隔离,传播,超时,只读)
主要用于事务的隔离,传播,只读等说明
TransactionStatus 事务具体运行状态
是否是一个新的事务,是否有保存点,事务是否完成等说明
首先通过TransactionDefinition定义了事务(隔离,传播,超时,只读)等信息后,再交给PlatformTransactionManager平台事务管理器进行真正的事务管理,之后事务会产生一些相应的状态,之后就会保存到TransactionStatus中。
3.1平台事务管理器PlatformTransactionManager
org.springframework.orm.hibernate3.HibernateTransactionManager使用Hibernate3.0版本进行持久化数据时使用
org.springframework.orm.jdo.JdoTransactionManager
持久化机制为jdao
org.springframework.orm.jpa.JpaTransactionManager
使用jpa进行持久化
org.springframework.transaction.jta.JtaTransactionManager使用JTA来实现事务管理,在一个事务跨越多个资源时必须使用
3.2事务定义信息接口 TransactionDefintion
3.2.1事务的脏读,不可重复读,幻读
不可重复读:在同一个事物中,多次读取同一数据,由于另外一个事务对该数据 修改提交,造成返回的结果不同。
幻读(虚读):一个事务读取几行记录后,另一个事务 插入或删除 了一些记录,导致再次读取的返回结果不同。
不同点在于,不可重复读侧重点在于修改并提提交,幻读(虚度)在于删除或添加
3.2.2 事务的隔离级别
READ_UNCOMMITED允许你读取还未提交的改变了的数据(可导致脏读,幻读,不可重复读)
READ_COMMINTED允许你读取事务已经提交后的数据(可防止脏读,但是幻读和不可重复读是有可能发生的)
REPEATABLE_READ对相同字段的多次读取是一致的,除非数据被事务本身改变(可防止脏读,不可重复读,当幻读任然可能发生)
SERIALIZABLE
完全服从ACID的隔离级别,确保不发生脏读,幻读,不可重复读。这在所有的隔离级别中是最慢的,他是典型的
通过完全锁定在事务中设计的数据表来完成的
- <span style="white-space:pre"> </span>ServiceA{
 - methoda(){//需要调用serviceB中的业务方法methodb()共同完成
 - dao1.xxmethod();
 - serviceB.methodb();
 - }
 - }
 - ServiceB{
 - methodb(){
 - dao2.yymethod();
 - }
 - }
 - DAO1{
 - xxmethod(){
 - }
 - }
 - DAO2{
 - yymethod(){
 - }
 - }
 
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。(就比如上边的场景,methoda假如有事务
则使用methoda的使用,假如methoda没有则新建一个事务)
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。(就比如上边的场景,methoda假如有事务
则使用methoda的使用,假如methoda没有则不使用事务)
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。(就比如上边的场景,methoda假如有事务
则使用methoda的使用,假如methoda没有则抛出异常)
类二,两者不再同一个事物中
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。(就比如上边的场景,methoda假如有事务挂起该事物
不使用,而methodb新建一个事务)
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。(就比如上边的场景,methoda假如有事务挂起该事物
不使用,而methodb不使用事务)
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。(就比如上边的场景,methoda假如有事务则抛出异常)
类三嵌套事务中
PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行(如果在执行methoda完成的时候,就会使用事务设置一个保存点,再执行methodb,假如methodb没有异常,他们就一起提交了,如果
发生了异常,你可根据自己的设定你可选择回滚到保存点位置,也可以回滚到最初的状态)  
3.3 事务具体运行状态接口 TransactionStatus
4.Spring中的事务实现方式
主要通过TransactionTemplate手动管理事务,在实际开发中很少使用
-使用XML配置声明
主要通过Spring的AOP实现的,在开发中推荐使用(代码入侵性小)
4.1Spring的编程式事务管理
管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。
对于编程式事务管理,spring推荐使用TransactionTemplate。
- create table account(
 - id number(20) primary key,
 - name varchar2(20),
 - money number
 - );
 - insert into account values(1,'张三',1000);
 - insert into account values(2,'李四',1000);
 - insert into account values(3,'王五',1000);
 
- jdbc.driver=oracle.jdbc.driver.OracleDriver
 - jdbc.url=jdbc:oracle:thin:@localhost:1521:XE
 - jdbc.username=xxx
 - jdbc.password=xxx
 
- <?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:context="http://www.springframework.org/schema/context"
 - xmlns:aop="http://www.springframework.org/schema/aop"
 - xsi:schemaLocation="http://www.springframework.org/schema/beans
 - http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
 - http://www.springframework.org/schema/aop
 - http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
 - http://www.springframework.org/schema/context
 - http://www.springframework.org/schema/context/spring-context.xsd">
 - <!-- 引入外部文件 -->
 - <context:property-placeholder location="classpath:db.properties"/>
 - <!-- 配置c3p0的连接池 -->
 - <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
 - <property name="driverClass">
 - <value>${jdbc.driver}</value>
 - </property>
 - <property name="jdbcUrl">
 - <value>${jdbc.url}</value>
 - </property>
 - <property name="user">
 - <value>${jdbc.username}</value>
 - </property>
 - <property name="password">
 - <value>${jdbc.password}</value>
 - </property>
 - </bean>
 - <!-- 配置业务层的类 -->
 - <bean id="accountService" class="com.xxx.spring.chap5.service.impl.AccountServiceImpl">
 - <property name="accountDao" ref="accountDao"></property>
 - <!-- 注入事务管理模板 -->
 - <property name="transactionTemplate" ref="transactionTemplate"></property>
 - </bean>
 - <!-- 配置dao,Dao继承了JdbcDaoSupport后,只要注入了连接池就会有模板,就可以通过模板对数据库进行相应的操作,可以参见源码-->
 - <bean id="accountDao" class="com.xx.spring.chap5.dao.impl.AccountDaoImpl">
 - <property name="dataSource" ref="dataSource"></property>
 - </bean>
 - <!-- 配置事务管理 -->
 - <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 - <property name="dataSource" ref="dataSource"></property>
 - </bean>
 - <!-- 配置事务管理模板,Spring为了简化事务管理的代码,提供了事务管理模板 -->
 - <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
 - <property name="transactionManager" ref="transactionManager"></property>
 - </bean>
 - </beans>
 
Service:业务逻辑接口
- /**
 - * 转账的业务接口
 - * */
 - public interface AccountService {
 - /**
 - * @param out 转出的账户
 - * @param in 转入的账户
 - * @param money 转账金额
 - * */
 - public void transfer(String out,String in,Double money);
 - }
 
Service业务逻辑实现
- import org.springframework.transaction.TransactionStatus;
 - import org.springframework.transaction.support.TransactionCallbackWithoutResult;
 - import org.springframework.transaction.support.TransactionTemplate;
 - import com.xxx.spring.chap5.dao.AccountDao;
 - import com.xxx.spring.chap5.service.AccountService;
 - /**
 - * 转账业务接口的具体实现
 - * */
 - public class AccountServiceImpl implements AccountService {
 - private AccountDao accountDao;
 - private TransactionTemplate transactionTemplate; //事务管理模板
 - public TransactionTemplate getTransactionTemplate() {
 - return transactionTemplate;
 - }
 - public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
 - this.transactionTemplate = transactionTemplate;
 - }
 - public AccountDao getAccountDao() {
 - return accountDao;
 - }
 - public void setAccountDao(AccountDao accountDao) {
 - this.accountDao = accountDao;
 - }
 - @Override
 - public void transfer(final String out, final String in, final Double money) {
 - //使用事务模板execute中需要传入TransactionCallback的实现类对象
 - transactionTemplate.execute(new TransactionCallbackWithoutResult() {
 - @Override
 - protected void doInTransactionWithoutResult(TransactionStatus arg0) {
 - accountDao.outMoney(out, money);
 - accountDao.inMoney(in, money);
 - }
 - });
 - }
 - }
 
持久层Dao层接口
- /**
 - * 转账的dao层接口
 - * */
 - public interface AccountDao {
 - /**
 - * @param out 转出账户
 - * @param money 转账金额
 - * */
 - public void outMoney(String out,Double money);
 - /**
 - * @param in 转入账户
 - * @param money 转账金额
 - * */
 - public void inMoney(String in,Double money);
 - }
 
持久层Dao接口实现
- import org.springframework.jdbc.core.support.JdbcDaoSupport;
 - import com.briup.spring.chap5.dao.AccountDao;
 - /**
 - * 转账的dao层接口实现
 - * Dao继承了JdbcDaoSupport后,只要注入了连接池就会有模板,就可以通过模板对数据库进行相应的操作,
 - * */
 - public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
 - @Override
 - public void outMoney(String out, Double money) {
 - String sql = "update account set money = money - ? where name = ?";
 - this.getJdbcTemplate().update(sql, money,out);
 - }
 - @Override
 - public void inMoney(String in, Double money) {
 - String sql = "update account set money = money + ? where name = ?";
 - this.getJdbcTemplate().update(sql, money,in);
 - }
 - }
 
测试:
- import org.junit.Test;
 - import org.springframework.context.ApplicationContext;
 - import org.springframework.context.support.ClassPathXmlApplicationContext;
 - import com.xxx.spring.chap5.service.AccountService;
 - /**
 - * 转账测试类
 - * */
 - public class SpringTransactionTest {
 - @Test
 - public void test1() throws Exception {
 - ApplicationContext ac = new ClassPathXmlApplicationContext("com/xxx/spring/chap5/applicationContext.xml");
 - AccountService accountService = ac.getBean("accountService",AccountService.class);
 - accountService.transfer("张三", "李四", 200.0);
 - }
 - }
 
数据库查询结果
- 1 张三 800
 - 2 李四 1200
 - 3 王五 1000
 
- @Override
 - public void transfer(final String out, final String in, final Double money) {
 - //使用事务模板TransactionCallback
 - transactionTemplate.execute(new TransactionCallbackWithoutResult() {
 - @Override
 - protected void doInTransactionWithoutResult(TransactionStatus arg0) {
 - accountDao.outMoney(out, money);
 - int i = 1/0;
 - accountDao.inMoney(in, money);
 - }
 - });
 - }
 
会发生异常java.lang.ArithmeticException: / by zero...
4.2Spring中声明式事务管理
在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,
这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明
(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。
4.2.1声明式事务管理-基于代理实现
- <?xml version="1.0" encoding="UTF-8"?>
 - <beans xmlns="http://www.springframework.org/schema/beans"
 - <span style="white-space:pre"> </span>xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
 - xmlns:aop="http://www.springframework.org/schema/aop"
 - xsi:schemaLocation="http://www.springframework.org/schema/beans
 - http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
 - http://www.springframework.org/schema/aop
 - http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
 - http://www.springframework.org/schema/context
 - http://www.springframework.org/schema/context/spring-context.xsd">
 - <!-- 声明式事务管理-代理实现 -->
 - <!-- 引入外部文件 -->
 - <context:property-placeholder location="classpath:db.properties"/>
 - <!-- 配置c3p0的连接池 -->
 - <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
 - <property name="driverClass">
 - <value>${jdbc.driver}</value>
 - </property>
 - <property name="jdbcUrl">
 - <value>${jdbc.url}</value>
 - </property>
 - <property name="user">
 - <value>${jdbc.username}</value>
 - </property>
 - <property name="password">
 - <value>${jdbc.password}</value>
 - </property>
 - </bean>
 - <!-- 配置业务层的类 -->
 - <bean id="accountService2" class="com.xxx.spring.chap5.service.impl.AccountServiceImpl2">
 - <property name="accountDao" ref="accountDao2"></property>
 - </bean>
 - <!-- 配置dao,Dao继承了JdbcDaoSupport后,只要注入了连接池就会有模板,就可以通过模板对数据库进行相应的操作,可以参见源码-->
 - <bean id="accountDao2" class="com.xxx.spring.chap5.dao.impl.AccountDaoImpl2">
 - <property name="dataSource" ref="dataSource"></property>
 - </bean>
 - <!-- 配置事务管理器 -->
 - <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 - <property name="dataSource" ref="dataSource"></property>
 - </bean>
 - <!-- 配置业务层的代理 -->
 - <bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
 - <!-- 配置目标类 -->
 - <property name="target" ref="accountService2"></property>
 - <!-- 注入事物管理器 -->
 - <property name="transactionManager" ref="transactionManager"></property>
 - <!-- 注入事物的相关属性,事物的隔离级别,传播行为等
 - key值为方法名可以使用通配符*
 - value值为
 - -->
 - <property name="transactionAttributes">
 - <props>
 - <!-- prop的格式
 - key为方法名,可以使用*通配符号
 - value值的格式:
 - 1. PROPAGATION :事务的传播行为
 - 2. ISOLATION :事务隔离级别
 - 3. readOnly :只读
 - 4. -Exception :发生那些异常回滚
 - 5. +Exception :发生那些事务不回滚
 - 之间使用,号隔开
 - -->
 - <prop key="trans*">PROPAGATION_REQUIRED</prop>
 - </props>
 - </property>
 - </bean>
 - </beans>
 
Service实现改为如下:
- import org.springframework.transaction.TransactionStatus;
 - import org.springframework.transaction.support.TransactionCallbackWithoutResult;
 - import org.springframework.transaction.support.TransactionTemplate;
 - import com.xxx.spring.chap5.dao.AccountDao;
 - import com.xxx.spring.chap5.service.AccountService;
 - /**
 - * 转账业务接口的具体实现
 - * */
 - public class AccountServiceImpl2 implements AccountService {
 - private AccountDao accountDao;
 - private TransactionTemplate transactionTemplate; //事务管理模板
 - public TransactionTemplate getTransactionTemplate() {
 - return transactionTemplate;
 - }
 - public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
 - this.transactionTemplate = transactionTemplate;
 - }
 - public AccountDao getAccountDao() {
 - return accountDao;
 - }
 - public void setAccountDao(AccountDao accountDao) {
 - this.accountDao = accountDao;
 - }
 - @Override
 - public void transfer(final String out, final String in, final Double money) {
 - accountDao.outMoney(out, money);
 - accountDao.inMoney(in, money);
 - }
 - }
 
Dao层不变
- /**
 - * 声明式事务管理--代理实现
 - * */
 - @Test
 - public void test2() throws Exception {
 - ApplicationContext ac = new ClassPathXmlApplicationContext("com/xxx/spring/chap5/applicationContext2.xml");
 - AccountService accountService = ac.getBean("accountServiceProxy",AccountService.class);//代理对象
 - accountService.transfer("张三", "李四", 200.0);
 - }
 
查询结果:
- <span style="white-space:pre"> </span>1 张三 800
 - 2 李四 1200
 - 3 王五 1000
 
假如Service中出现异常:
- @Override
 - public void transfer(final String out, final String in, final Double money) {
 - accountDao.outMoney(out, money);
 - int i = 1/0;
 - accountDao.inMoney(in, money);
 - }
 
会抛出异常
java.lang.ArithmeticException: / by zero
但是钱没有多,也没有少,意思是本次操作失败会,保证账户的安全
4.2.2声明式事务管理-基于AspectJ实现
- <?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:context="http://www.springframework.org/schema/context"
 - xmlns:tx="http://www.springframework.org/schema/tx"
 - xmlns:aop="http://www.springframework.org/schema/aop"
 - xsi:schemaLocation="http://www.springframework.org/schema/beans
 - http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
 - http://www.springframework.org/schema/tx
 - http://www.springframework.org/schema/tx/spring-tx.xsd
 - http://www.springframework.org/schema/aop
 - http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
 - http://www.springframework.org/schema/context
 - http://www.springframework.org/schema/context/spring-context.xsd">
 - <!-- 基于AspectJ的声明式事务管理 -->
 - <!-- 引入外部文件 -->
 - <context:property-placeholder location="classpath:db.properties" />
 - <!-- 配置c3p0的连接池 -->
 - <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
 - <property name="driverClass">
 - <value>${jdbc.driver}</value>
 - </property>
 - <property name="jdbcUrl">
 - <value>${jdbc.url}</value>
 - </property>
 - <property name="user">
 - <value>${jdbc.username}</value>
 - </property>
 - <property name="password">
 - <value>${jdbc.password}</value>
 - </property>
 - </bean>
 - <!-- 配置业务层的类 -->
 - <bean id="accountService2" class="com.xxx.spring.chap5.service.impl.AccountServiceImpl2">
 - <property name="accountDao" ref="accountDao2"></property>
 - </bean>
 - <!-- 配置dao,Dao继承了JdbcDaoSupport后,只要注入了连接池就会有模板,就可以通过模板对数据库进行相应的操作,可以参见源码 -->
 - <bean id="accountDao2" class="com.xxx.spring.chap5.dao.impl.AccountDaoImpl2">
 - <property name="dataSource" ref="dataSource"></property>
 - </bean>
 - <!-- 配置事务管理器 -->
 - <bean name="transactionManager"
 - class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 - <property name="dataSource" ref="dataSource"></property>
 - </bean>
 - <!-- 配置事务通知 -->
 - <tx:advice id="txAdvice" transaction-manager="transactionManager">
 - <!-- 设置事物属性 -->
 - <tx:attributes>
 - <!-- 设置各种方法的
 - propagation 为传播行为
 - isolation 事务的隔离级别
 - read-only 设置之都属性
 - rollback-for 发生生么异常回滚
 - no-rollback-for 发生那些异常不回滚
 - -->
 - <tx:method name="tran*" propagation="REQUIRED" read-only="true" />
 - <tx:method name="get*" propagation="REQUIRED" read-only="true" />
 - <tx:method name="find*" propagation="REQUIRED" read-only="true" />
 - <tx:method name="save*" propagation="REQUIRED" read-only="false"
 - rollback-for="java.lang.Exception" />
 - <tx:method name="insert*" propagation="REQUIRED" read-only="false"
 - rollback-for="java.lang.Exception" />
 - <tx:method name="update*" propagation="REQUIRED" read-only="false"
 - rollback-for="java.lang.Exception" />
 - <tx:method name="delete*" propagation="REQUIRED" read-only="false"
 - rollback-for="java.lang.Exception" />
 - <tx:method name="*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
 - </tx:attributes>
 - </tx:advice>
 - <!-- 配置AOP -->
 - <aop:config>
 - <!-- 配置切入点,表示切入点为类AccountServiceImpl2下的所有方法 -->
 - <aop:pointcut
 - expression="execution(* com.xxx.spring.chap5.service.impl.AccountServiceImpl2.*(..))"
 - id="pointcut" />
 - <!-- 配置切面,表示AccountServiceImpl2下的所有方法都使用txAdivice增强 -->
 - <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />
 - </aop:config>
 - </beans>
 
Service实现
- import org.springframework.transaction.annotation.Propagation;
 - import org.springframework.transaction.annotation.Transactional;
 - import org.springframework.transaction.support.TransactionTemplate;
 - import com.xxx.spring.chap5.dao.AccountDao;
 - import com.xxx.spring.chap5.service.AccountService;
 - /**
 - * 转账业务接口的具体实现
 - *
 - * */
 - public class AccountServiceImpl2 implements AccountService {
 - private AccountDao accountDao;
 - private TransactionTemplate transactionTemplate; //事务管理模板
 - public TransactionTemplate getTransactionTemplate() {
 - return transactionTemplate;
 - }
 - public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
 - this.transactionTemplate = transactionTemplate;
 - }
 - public AccountDao getAccountDao() {
 - return accountDao;
 - }
 - public void setAccountDao(AccountDao accountDao) {
 - this.accountDao = accountDao;
 - }
 - @Override
 - public void transfer(final String out, final String in, final Double money) {
 - accountDao.outMoney(out, money);
 - accountDao.inMoney(in, money);
 - }
 - }
 
测试:
- /**
 - * 声明式事务管理-基于AspectJ实现
 - * */
 - @Test
 - public void test3() throws Exception {
 - ApplicationContext ac = new ClassPathXmlApplicationContext("com/xxx/spring/chap5/applicationContext3.xml");
 - AccountService accountService = ac.getBean("accountService2",AccountService.class);
 - accountService.transfer("张三", "李四", 200.0);
 - }
 
查询结果:
- 1 张三 800
 - 2 李四 1200
 - 3 王五 1000
 
4.2.3声明式事务管理-基于注解实现
- <?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:context="http://www.springframework.org/schema/context"
 - xmlns:tx="http://www.springframework.org/schema/tx"
 - xmlns:aop="http://www.springframework.org/schema/aop"
 - xsi:schemaLocation="http://www.springframework.org/schema/beans
 - http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
 - http://www.springframework.org/schema/aop
 - http://www.springframework.org/schema/aop/spring-aop-3.2.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">
 - <!-- 基于注解式事务管理 -->
 - <!-- 引入外部文件 -->
 - <context:property-placeholder location="classpath:db.properties" />
 - <!-- 配置c3p0的连接池 -->
 - <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
 - <property name="driverClass">
 - <value>${jdbc.driver}</value>
 - </property>
 - <property name="jdbcUrl">
 - <value>${jdbc.url}</value>
 - </property>
 - <property name="user">
 - <value>${jdbc.username}</value>
 - </property>
 - <property name="password">
 - <value>${jdbc.password}</value>
 - </property>
 - </bean>
 - <!-- 配置业务层的类 -->
 - <bean id="accountService2" class="com.xxx.spring.chap5.service.impl.AccountServiceImpl2">
 - <property name="accountDao" ref="accountDao2"></property>
 - </bean>
 - <!-- 配置dao,Dao继承了JdbcDaoSupport后,只要注入了连接池就会有模板,就可以通过模板对数据库进行相应的操作,可以参见源码 -->
 - <bean id="accountDao2" class="com.xxx.spring.chap5.dao.impl.AccountDaoImpl2">
 - <property name="dataSource" ref="dataSource"></property>
 - </bean>
 - <!-- 配置事务管理器 -->
 - <bean name="transactionManager"
 - class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 - <property name="dataSource" ref="dataSource"></property>
 - </bean>
 - <!-- 注解事务管理器配置 -->
 - <tx:annotation-driven transaction-manager="transactionManager"/>
 - </beans>
 
Sservice业务层实现:
- import org.springframework.transaction.annotation.Propagation;
 - import org.springframework.transaction.annotation.Transactional;
 - import org.springframework.transaction.support.TransactionTemplate;
 - import com.xxx.spring.chap5.dao.AccountDao;
 - import com.xxx.spring.chap5.service.AccountService;
 - /**
 - * 转账业务接口的具体实现
 - *
 - * @Transactional中注解的属性:
 - * propagation:事务的传播行为
 - * isolation:事务的隔离级别
 - * readOnly:是否只读
 - * rollbackFor:发生那些异常回滚
 - * noRollbackFor:发生那些异常不回滚,这些默认可以不写使用@Transactional就行
 - * */
 - @Transactional(propagation=Propagation.REQUIRED,readOnly=true,rollbackFor={RuntimeException.class, Exception.class})
 - public class AccountServiceImpl2 implements AccountService {
 - private AccountDao accountDao;
 - public AccountDao getAccountDao() {
 - return accountDao;
 - }
 - public void setAccountDao(AccountDao accountDao) {
 - this.accountDao = accountDao;
 - }
 - @Override
 - public void transfer(final String out, final String in, final Double money) {
 - accountDao.outMoney(out, money);
 - accountDao.inMoney(in, money);
 - }
 - }
 
测试:
- /**
 - * 4声明式事务管理-基于注解的实现
 - * */
 - @Test
 - public void test4() throws Exception {
 - ApplicationContext ac = new ClassPathXmlApplicationContext("com/xxx/spring/chap5/applicationContext4.xml");
 - AccountService accountService = ac.getBean("accountService2",AccountService.class);
 - accountService.transfer("张三", "李四", 200.0);
 - }
 
查询结果:
- 1 张三 800
 - 2 李四 1200
 - 3 王五 1000
 
转:Spring中事物管理的更多相关文章
- [原创]java WEB学习笔记109:Spring学习---spring中事物管理
		
博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好 ...
 - SSM-Spring-21:Spring中事物的使用案例
		
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 股票买卖案例(我会用三种开启事物的方法 代理工厂bean版的,注解版的,aspectj xml版的) 简单的介 ...
 - spring对数据库的操作、spring中事务管理的介绍与操作
		
jdbcTemplate的入门 创建maven工程 此处省略 导入依赖 <!-- https://mvnrepository.com/artifact/org.springframework/s ...
 - Spring中Bean管理的常用注解
		
在Spring中,主要用于管理bean的注解分为四大类:1.用于创建对象.2.用于给对象的属性注入值.3.用于改变作用的范围.4.用于定义生命周期.这几个在开发中经常接触到,也可以说每天都会遇见.其中 ...
 - 关于spring中事务管理的几件小事
		
1.Spring中的事务管理 作为企业级应用程序框架,Spring在不同的事务管理API之上定义了一个抽象层.而应用程序开发人员不必了解底层的事务管理API,就可以使用Spring的事务管理机制. S ...
 - Spring中事务管理的两种方式
		
spring支持编程式事务管理和声明式事务管理两种方式. 编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager.对于编程式事务 ...
 - Spring中事务管理
		
spring事务管理两种方式 第一种 编程式事务管理(不用) 第二种 声明式事务管理 (1) 基于xml配置文件实现 (2) 基于注解实现 一:声明式事务管理(xml配置) 第一步 ...
 - Oracle在Java中事物管理
		
对于 对数据库中的数据做dml操作时,能够回滚,这一事物是很重要的 下面例子是对数据库中数据进行修改 package com.demo.oracle; import java.sql.Connecti ...
 - spring的事物管理配置
		
基于注解的事务管理器配置(AOP) 首先要引入AOP和TX的名称控件 <!-- 使用annotation定义事务 --> <tx:annotation-driven transact ...
 
随机推荐
- 【刷题】洛谷 P4320 道路相遇
			
题目描述 在 H 国的小 w 决定到从城市 \(u\) 到城市 \(v\) 旅行,但是此时小 c 由于各种原因不在城市 \(u\),但是小 c 决定到在中途与小 w 相遇 由于 H 国道路的原因,小 ...
 - VS2010 代码突然改变字体 解决办法
			
sfsfsddffs dffsfsfsfsf 如上,第一行是突然变成宽体的字体,第二行是恢复后的字体,方法就是: shift+空格键,一起按就会在这两种字体之间变换~
 - 解题:THUWC 2017 在美妙的数学王国中畅游
			
题面 _“数字和数学规律主宰着这个世界.”_ 在 @i207M 帮助下折腾了半天终于搞懂了导数和泰勒展开,引用某学长在考场上的感受:感觉整个人都泰勒展开了 显然是个奇奇怪怪的东西套上LCT,发现直接维 ...
 - Linux上查找
			
locate 用法:locate filename locate是Linux系统中的一个查找(定位)文件命令,和find命令等找寻文件的工作原理类似,但locate是通过生成一个文件和文件夹的索引数据 ...
 - 修改Visual Studio项目中程序集信息默认公司名称的两种方法
			
这个公司名就是安装系统时注册的单位名称.可以通过修改注册表修改 Windows 系统的注册信息,方法如下:1.在开始"运行"中输入regedit,打开注册表编辑器.2.依次展开:H ...
 - Flask script 内的Shell 类 使用
			
1.集成Python shell 每次自动shell会话都要导入数据库实例和模型,很烦人.为了避免一直重复导入,我们可以做些配置让Flask-Script的Shell命令自动导入特定的对象.若想把对象 ...
 - 原始套接字-自定义IP首部和TCP首部
			
/* ===================================================================================== * * Filenam ...
 - LaTeX字体设置
			
% 导言区 % 帮助文档 texdoc lshort-zh % 设置normalsize大小 \documentclass[10pt]{ctexart} %article,ctexbook封面, ct ...
 - spring中bean配置和注入场景分析
			
bean与spring容器的关系 Bean配置信息定义了Bean的实现及依赖关系,Spring容器根据各种形式的Bean配置信息在容器内部建立Bean定义注册表,然后根据注册表加载.实例化Bean,并 ...
 - css中实现ul两端的li对齐外面边缘
			
其实就是设置ul的宽度大一些就好