SPRING事务_2

参照资料:Spring资料  http://www.cnblogs.com/charles999/p/6699113.html

 上篇:Spring事务_1

jdbc.properties 文件的配置

----------------------------

Spring支持两种方式事务管理

-编程式事务管理

  ·实际应用中很少使用

  ·通过TransactionTemplate手动管理事务

-使用XML配置声明式事务管理

  ·开发中推荐使用(代码侵入性最小)

  ·Spring的声明式事务是通过AOP实现的

---转账环境搭建(http://www.imooc.com/video/9330)--------------------------------------------------------

创建数据表account
CREATE TABLE `account` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `money` double DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `account` VALUES ('1', 'aaa', '1000');
INSERT INTO `account` VALUES ('2', 'bbb', '1000');
INSERT INTO `account` VALUES ('3', 'ccc', '1000');

----interface define-------------------------------------------------------

AccountDao

AccountService

----interface implement-------------------------------------------------------

 

项目实例:银行转账
第一步:AccountDao.java AccountDaoImpl.java

public interface AccountDao {
  public void outMoney(String out,Double money);
  public void inMoney(String in,Double money);
}

 

   AccountDaoImpl.java

public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
  public void outMoney(String out,Double money) {
    String sql="update account set money=money-? where name=?";
    this.getJdbcTemplate().update(sql, money, out);
  }  
  public void inMoney(String in,Double money) {
    String sql="update account set money=money+? where name=?";
    this.getJdbcTemplate().update(sql, money, in);
  }  
}

 


第二步:AccountService.java AccountServiceImpl.java

public interface AccountService {
    public void tranfer(String out,String in,Double money);
}

 以下蓝色字为匿名内部类

transactionTemplate.execute(new TransactionCallbackWithoutResult() { //如果匿名内部类要拿到外层包裹它的方法的参数,那么要将final修饰成final
      @Override       

      protected void doInTransactionWithoutResult(TransactionStatus arg0) { // TODO Auto-generated method stub
        accountDao.outMoney(out, money);

        int i=1/0;//发生异常

        accountDao.inMoney(in, money);

      }

});

public class AccountServiceImpl implements AccountService {
  //注入DAO类
  private AccountDao accountDao;

  public void setAccountDao(AccountDao accountDao) {
    this.accountDao = accountDao;
  }
  //注入事务管理的模板
  private TransactionTemplate transactionTemplate;

  public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
    this.transactionTemplate = transactionTemplate;
  }
  public void tranfer(final String out,final String in,final Double money) {
    transactionTemplate.execute(new TransactionCallbackWithoutResult() { //如果匿名内部类要拿到外层包裹它的方法的参数,那么要将final修饰成final
      @Override 
      protected void doInTransactionWithoutResult(TransactionStatus arg0) {
        // TODO Auto-generated method stub
        accountDao.outMoney(out, money);
        int i=1/0;//发生异常
        accountDao.inMoney(in, money);
      }
    }); 
  }
}

 

第三步:xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans
 3 xmlns="http://www.springframework.org/schema/beans"
 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5 xmlns:aop="http://www.springframework.org/schema/aop"
 6 xmlns:p="http://www.springframework.org/schema/p"
 7 xmlns:context="http://www.springframework.org/schema/context"
 8 xsi:schemaLocation="http://www.springframework.org/schema/beans 
 9 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
10 http://www.springframework.org/schema/context
11 http://www.springframework.org/schema/context/spring-context-3.0.xsd
12 http://www.springframework.org/schema/aop
13 http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> 
14 <!-- 引入外部的属性文件 -->
15 <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
16 <!-- 配置连接池 -->
17 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
18 <property name="driverClass" value="${jdbc.driverClass}"></property>
19 <property name="jdbcUrl" value="${jdbc.url}"></property>
20 <property name="user" value="${jdbc.username}"></property>
21 <property name="password" value="${jdbc.password}"></property>
22 </bean>
23 
24 <!-- 配置业务层 -->
25 <bean id="accountService" class="com.imooc.demo1.AccountServiceImpl">
26 <property name="accountDao" ref="accountDao"></property>
27 <!-- 注入事务管理的模板 -->
28 <property name="transactionTemplate" ref="transactionTemplate"></property>
29 </bean>
30 <!-- 配置DAO层 -->
31 <bean id="accountDao" class="com.imooc.demo1.AccountDaoImpl">
32 <property name="dataSource" ref="dataSource"></property> 
33 </bean> 
34 
35 <!-- 配置事务管理器 -->
36 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
37 <property name="dataSource" ref="dataSource"></property>
38 </bean>
39 
40 <!-- 配置事务管理的模板:Spring为了简化事务管理的代码而提供的类 -->
41 <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
42 <property name="transactionManager" ref="transactionManager"></property>
43 </bean>
44 
45 </beans>

27-29 注入事务管理的模板(通过set方法注入)

35-38 配置事务管理器

40-43 配置事务管理的模板:Spring为了简化事务管理的代码而提供的类

 

测试类:第三步没有配置事务管理时(27-29 35-38 40-43)

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContestConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
*转账测试类
*/

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class SpringDemo1 {
    //注解注入
    @Resource(name="accountService") 
    private AccountService accountService;

    @Test
    public void demo1(){
        accountService.tranfer("aaa", "bbb", 200);
    }
}

 

错误信息:

2017-06-22 11:15:00,866 [main] DEBUG [org.springframework.transaction.support.TransactionTemplate] - Initiating transaction rollback on application exception
java.lang.ArithmeticException: / by zero
	at com.imooc.transaction.AccountServiceImpl$1.doInTransactionWithoutResult(AccountServiceImpl.java:30)
	at org.springframework.transaction.support.TransactionCallbackWithoutResult.doInTransaction(TransactionCallbackWithoutResult.java:34)
	at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
	at com.imooc.transaction.AccountServiceImpl.transfer(AccountServiceImpl.java:26)
	at com.imooc.test.TestTransaction.testAspect(TestTransaction.java:22)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:233)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:176)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
2017-06-22 11:15:00,867 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Initiating transaction rollback
2017-06-22 11:15:00,868 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Rolling back JDBC transaction on Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@662ac478]
2017-06-22 11:15:00,936 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Releasing JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@662ac478] after transaction
2017-06-22 11:15:00,936 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Returning JDBC Connection to DataSource
2017-06-22 11:15:00,937 [main] DEBUG [com.mchange.v2.resourcepool.BasicResourcePool] - trace com.mchange.v2.resourcepool.BasicResourcePool@7dcf94f8 [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@248c3047)
2017-06-22 11:15:00,938 [main] DEBUG [org.springframework.test.context.support.DirtiesContextTestExecutionListener] - After test method: context [DefaultTestContext@256216b3 testClass = TestTransaction, testInstance = com.imooc.test.TestTransaction@2a18f23c, testMethod = testAspect@TestTransaction, testException = java.lang.ArithmeticException: / by zero, mergedContextConfiguration = [MergedContextConfiguration@d7b1517 testClass = TestTransaction, locations = '{classpath:spring-transaction.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]], class dirties context [false], class mode [null], method dirties context [false].
2017-06-22 11:15:00,941 [main] DEBUG [org.springframework.test.context.support.DirtiesContextTestExecutionListener] - After test class: context [DefaultTestContext@256216b3 testClass = TestTransaction, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration@d7b1517 testClass = TestTransaction, locations = '{classpath:spring-transaction.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]], dirtiesContext [false].
2017-06-22 11:15:00,942 [Thread-1] INFO  [org.springframework.context.support.GenericApplicationContext] - Closing org.springframework.context.support.GenericApplicationContext@7a79be86: startup date [Thu Jun 22 11:14:59 CST 2017]; root of context hierarchy
2017-06-22 11:15:00,943 [Thread-1] DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Returning cached instance of singleton bean 'lifecycleProcessor'
2017-06-22 11:15:00,945 [Thread-1] DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@10a035a0: defining beans [org.springframework.context.support.PropertySourcesPlaceholderConfigurer#0,dataSource,accountService,accountDao,transactionManager,transactionTemplate,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor]; root of factory hierarchy
2017-06-22 11:15:00,945 [Thread-1] DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Retrieved dependent beans for bean 'accountService': [com.imooc.test.TestTransaction]

 


---6-1 Spring声明式编程:使用XML (原始方式)-----------------------------------------------------------------
Spring声明式编程:使用XML (原始方式)

1 引入包(以AOP形式开发,AOP传统开发需要以下两个包)

2 com.springsource.org.aopalliance-1.0.0.jar  AOP联盟包

spring-aop-3.2.0.RELEASE.jar  AOP包

配置:

1 <!-- 配置事务管理器 --> 配置dateSource属性
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"></property>
</bean>

2 <!-- 配置业务层的管理 --> //对目标进行增强
<bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
  <!-- 配置目标对象 -->
  <property name="target" ref="accountService"></property>
  <!-- 注入事务管理器 -->
  <property name="transactionManager" ref="transactionManager"></property>
  <!-- 注入事务属性 -->
  <property name="transactionAttributes">
    <props>
      <!-- prop的格式:

        * PROPAGATION:事务的传播行为

        * ISOLATION  :事务的隔离级别

        * readOnly  : 只读

        * -Exception 发生哪些异常回滚事务

        * +Exception 发生哪些异常事务不回滚

      -->

      //类里的方法,tranfer方法。("*"代表所有方法,此处也可用,因为只有tranfer一个方法)
      <prop key="tranfer">PROPAGATION_REQUIRED,+java.lang.ArithmeticException</prop>
    </props>
  </property>
</bean>
第一步:

<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> 
<!-- 引入外部的属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!-- 配置连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  <property name="driverClass" value="${jdbc.driverClass}"></property>
  <property name="jdbcUrl" value="${jdbc.url}"></property>
  <property name="user" value="${jdbc.username}"></property>
  <property name="password" value="${jdbc.password}"></property>
</bean>

<!-- 配置业务层 -->
<bean id="accountService" class="com.imooc.demo2.AccountServiceImpl">
  <property name="accountDao" ref="accountDao"></property>
</bean>
<!-- 配置DAO层 -->
<bean id="accountDao" class="com.imooc.demo2.AccountDaoImpl">
  <property name="dataSource" ref="dataSource"></property> 
</bean> 

<!-- 配置事务管理器 -->
<bean id="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="accountService"></property>
  <!-- 注入事务管理器 -->
  <property name="transactionManager" ref="transactionManager"></property>
  <!-- 注入事务属性 -->
  <property name="transactionAttributes">
    <props>
      <!-- 
      prop的格式:
      * PROPAGATION 事务的传播行为
      * ISOLATION 事务的隔离级别
      * readOnly 只读(不可更新,插入和删除)
      * -Exception 发生哪些异常回滚事务
      * +Exception 发生哪些异常事务不回滚(,+java.lang.ArithmeticException 就是1/0的异常,此时发生也正常处理)
      -->
      <prop key="tranfer">PROPAGATION_REQUIRED,+java.lang.ArithmeticException</prop>
    </props>
  </property>
</bean>
</beans>

 

service类
public class AccountServiceImpl implements AccountService {
  //注入DAO类
  private AccountDao accountDao;

  public void setAccountDao(AccountDao accountDao) {
    this.accountDao = accountDao;
  }

  public void tranfer(final String out,final String in,final Double money) {
    accountDao.outMoney(out, money);
    int i=1/0;//发生异常
    accountDao.inMoney(in, money);
  }
}

 


第二步:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class Demo2Test {
  //配置 注入代理类(代理类被增强了) accountServiceProxy
  //@Resource(name="accountService")
     @Resource(name="accountServiceProxy") 
  private AccountService accountService;

  @Test
  public void demo2(){
    accountService.tranfer("aaa", "bbb", 200d);
  }
}

 

---6-2 声明式事务管理方式二:基于AspectJ的XML方式----------------------------------------------------------------------

Spring声明式编程:使用XML(AspectJ方式)

JAR包:

com.springsource.org.aspectj.weaver-1.6.8.RELEASE

spring-aspects-3.2.0.RELEASE
第一步

引入约束:
<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"

xmlns:tx="http://www.springframework.org/schema/tx"

xmlns:task="http://www.springframework.org/schema/task"

xsi:schemaLocation="http://www.springframework.org/schema/beans    

    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context-3.1.xsd

    http://www.springframework.org/schema/aop

    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd

    http://www.springframework.org/schema/tx

    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd

    http://www.springframework.org/schema/task

    http://www.springframework.org/schema/task/spring-task-3.1.xsd">

 

<?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"
     xmlns:tx="http://www.springframework.org/schema/tx"
     xmlns:task="http://www.springframework.org/schema/task"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.1.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
         http://www.springframework.org/schema/tx
         http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
         http://www.springframework.org/schema/task
         http://www.springframework.org/schema/task/spring-task-3.1.xsd">

    <!-- 引入外部的属性文件 -->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    
    <!-- 配置c3p0连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}" />
        <property name="jdbcUrl" value="${jdbc.url}" />
        <property name="user" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>
    
    <!-- 配置业务层类 -->
    <bean id="accountService" class="com.zs.spring.demo3.AccountServiceImpl">
        <property name="accountDao" ref="accountDao" />
    </bean>
    
    <!-- 配置DAO类(简化,会自动配置JdbcTemplate) -->
    <bean id="accountDao" class="com.zs.spring.demo3.AccountDaoImpl">
        <property name="dataSource" ref="dataSource" />
    </bean>
    
    <!-- ==================================3.使用XML配置声明式的事务管理,基于tx/aop=============================================== -->
    
    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    
    <!-- 配置事务的通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 
                propagation    :事务传播行为
                isolation    :事务的隔离级别
                read-only    :只读
                rollback-for:发生哪些异常回滚
                no-rollback-for    :发生哪些异常不回滚
                timeout        :过期信息
             -->
            <tx:method name="transfer" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    
    <!-- 配置切面 -->
    <aop:config>
        <!-- 配置切入点 -->
        <aop:pointcut expression="execution(* com.zs.spring.demo3.AccountService+.*(..))" id="pointcut1"/>
        <!-- 配置切面 -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
    </aop:config>

</beans>

*代表方法返回值(*为任意返回值) 

+代表子类

<aop:pointcut expression="execution(* com.zs.spring.demo3.AccountService+.*(..))" id="pointcut1"/>

advisor:一个切入点一个通知时使用(aspect多个切入点和多个通知时使用)

<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>

    <!-- 配置事务的通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- propagation :事务传播行为

      isolation :事务的隔离级别

      read-only :只读

      rollback-for:发生哪些异常回滚

      no-rollback-for :发生哪些异常不回滚

      timeout :过期信息 -->
            <tx:method name="transfer" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

     <!-- 配置切面 -->
    <aop:config>
        <!-- 配置切入点 -->
        <aop:pointcut expression="execution(* com.zs.spring.demo3.AccountService+.*(..))" id="pointcut1"/>
        <!-- 配置切面 :在"pointcut1"切入点上用"txAdvice"增强-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
    </aop:config>

 


第二步:测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext3.xml")
public class Demo3Test {
  @Resource(name="accountService")
  private AccountService accountService;

  @Test
  public void demo3(){
    accountService.tranfer("aaa", "bbb", -200d);
  }
}

----6-3 Spring声明式编程:使用XML(注解方式)-----------------------------------------------------------------------------------------------
Spring声明式编程:使用XML(注解方式)
第一步:

1. 配置事务管理器
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <!-- 注入连接池 -->
  <property name="dataSource" ref="dataSource"></property>
</bean>
2. 开启注解事务
<!-- 开启注解事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

3.在业务层添加注解

/*
* @Transactional注解属性: *
* propagation:事务传播行为
isolation:事务隔离级别
readOnly:只读
rollBbackFor:发生哪些异常回滚
noRollbackFor:发生哪些异常不回滚
*/

@Transactional//不添加注解property时,采用默认值
//@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,readOnly=false) 可添加注解property
public class AccountServiceImpl implements AccountService {

<?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"
     xmlns:tx="http://www.springframework.org/schema/tx"
     xmlns:task="http://www.springframework.org/schema/task"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.1.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
         http://www.springframework.org/schema/tx
         http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
         http://www.springframework.org/schema/task
         http://www.springframework.org/schema/task/spring-task-3.1.xsd">

    <!-- 引入外部的属性文件 -->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    
    <!-- 配置c3p0连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}" />
        <property name="jdbcUrl" value="${jdbc.url}" />
        <property name="user" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>
    
    <!-- 配置业务层类 -->
    <bean id="accountService" class="com.zs.spring.demo4.AccountServiceImpl">
        <property name="accountDao" ref="accountDao" />
    </bean>
    
    <!-- 配置DAO类(简化,会自动配置JdbcTemplate) -->
    <bean id="accountDao" class="com.zs.spring.demo4.AccountDaoImpl">
        <property name="dataSource" ref="dataSource" />
    </bean>
    
    <!-- ==================================4.使用注解配置声明式事务============================================ -->

    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    
    <!-- 开启注解事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
</beans>

 

第二步:
/*
* @Transactional注解属性: *
* propagation:事务传播行为
isolation:事务隔离级别
readOnly:只读
rollBbackFor:发生哪些异常回滚
noRollbackFor:发生哪些异常不回滚
*/
@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,readOnly=false)
public class AccountServiceImpl implements AccountService {

---7 事务总结----------------------------------------------------------------

Spring将事务管理分成了两类:
 1. 编程式事务管理
  手动编写代码进行事务管理.(很少使用)
 2. 声明式事务管理:
  * 基于TransactionProxyFactoryBean的方式.(很少使用)
  * 需要为每个进行事务管理的类,配置一个TransactionProxyFactoryBean进行增强.
  * 基于AspectJ的XML方式.(经常使用)
      1)XML可很清晰的看到那些类配置了事务管理

    2)一旦配置好之后,类上不需要添加任何东西
  * 基于注解方式.(经常使用)
      1) 配置简单,需要在业务层上添加一个@Transactional的注解.
  

=================================================
总结:
Spring的编程式事务管理(事务管理模板)(很少使用)
1.通过TrasactionTemplate手动管理事务
2.在AccountService中使用TransactionTemplate
3.TransactionTemplate依赖DataSourceTransactionManager
4.DataSourceTransactionManager依赖DataSource构造

(事务管理器有了连接池才能获得链接进行事务管理)


Spring的声明式事务管理(通过AOP实现的)
第一种:基于代理TransactionProxyFactoryBean;
注入:目标,事务管理器,事务属性:
1.PROPAGATION :事务的传播行为
2.ISOLATION :事务的隔离级别
3.readOnly :只读,(不可以进行修改,插入,删除)
4.-Exception :发生那些异常回滚事务
5.+Exception :发生那些异常事务不回滚
第二种:基于AspectJ的XML方式(aspectJ的话,就是分的更加的详细,切入点(类),切入面(方法))
1.配置事务的通知<tx>
2.配置切面,切点<aop>
第三种:基于注解的方式
1.开启事务<tx:annotation-driven transaction-Manager="" />
2.service类@Transactional(name=value)

 ======================================================

事务的特性:
事务是一个不可分割的工作单位,所有操作要么全部执行,要么都不执行
1.原子性: 指的是事物是一个不可分割的部分,要么都发生。要么都不发生
2.隔离性: 多个并发事物之间数据要相互隔离
3.一致性: 事物处理前后数据的完整性必须保持一致
4.持久性: 一个事物被提交之后。它对数据库中数据的改变是持久的

Spring事务管理接口
PlatformTransationManager:事务管理器
TransactionDefinition:事务定义信息(隔离、传播、超时、只读)
TransactionStatus:事务具体运行状态

PlatformTransactionManager
spring为了不同的持久化框架提供了不同的PlatformTransactionManagerPlatgorfTransactionManager的实现类
org.springframework.jdbc.datasource.DataSourceTransactionManager:使用Spring JDBC或iBatis进行持久化数据时
org.springframework.orm.hibernate3.HibernateTransactionManager:使用Hibernate3.0版本进行持久化数据时
org.springframework.orm.jpa.JpaTransactionManager:使用JPA进行持久化时
org.springframework.orm.jdo.JdoTransactionManager:当持久化机制是Jdo时
org.springframework.transaction.jta.JtaTransactionManager:使用一个JTA来管理事务,在一个事务跨越越多个资源时必须使用

七种事务传播路径
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--该方法只能在一个已经存在的事务中执行,业务方法不能发起自己的事务。如果在没有事务的环境下被调用,容器抛出例外。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

事务隔离级别:
脏读:一个事务读取了另一个事务改写但未提交的数据,如果这些数据回滚则读到的数据是无效的。
不可重复读:一个事务读取了另一个事务提交的更新数据
幻读:一个事务读取了另一个事务插入的数据

Spring事务的隔离级别
TransactionDefinition接口的常量中ISOLATION_开头的表示事物的隔离级别
1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别. 另外四个与JDBC的隔离级别相对应
2. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。 这种隔离级别会产生脏读,不可重复读和幻像读。
3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。 它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
5. ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。 除了防止脏读,不可重复读外,还避免了幻像读。
MySQL默认事务隔离级别:REPATABLE_READ(可能出现幻读)
Oracle默认:READ_COMMITTED(可能出现不可重复读和幻读)

Spring编程式事务管理
(1)在AccountService中使用TransactionTemplate
(2)TransactionTemplate依赖DataSourceTransactionManager
(3)DataSourceTransactionManager依赖DataSource构造

posted @ 2017-04-12 14:56  charles999  阅读(202)  评论(0编辑  收藏  举报