一、关于是事务

  以方法为单位,进行事务控制;抛出异常,事务回滚。



  最小的执行单位为方法。决定执行成败是通过是否抛出异常来判断的,抛出异常即执行失败



 

二、声明式事务:



声明式事务(declarative transaction management)是 Spring提供的对程序事务管理的方式之一。



Spring的声明式事务顾名思义就是采用声明的方式来处理事务。这里所说的声明,就是指在配置文件中声明。用在Spring配置文件中声明式的处理事务来代替代码式的处理事务。这样的好处是,事务管理不侵入开发的组件,具体来说,业务逻辑对象就不会意识到正在事务管理之中,事实上也应该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策划的话,也只需要在 定义文件中重新配置即可;在不需要事务管理的时候,只要在设定文件上修改一下,即可移去事务管理服务,无需改变代码重新编译,这样维护起来极其方便。



Spring使用 AOP来完成声明式的事务管理,因而声明式事务是以方法为单位,Spring的事务属性自然就在于描述事务应用至方法上的策略,在Spring中事务属性有以下四个参数:



1.传播行为



2. 隔离级别



3.只读提示



4.事务超时期间



 

三、案例:编程实现购买的业务

 

配置Spring的声明式事务管理 spring 声明式事务_数据库

 

配置Spring的声明式事务管理 spring 声明式事务_java_02

配置Spring的声明式事务管理 spring 声明式事务_bc_03

  1.编写实体类

  2.编写dao层接口和实现

  3.编写service层接口和实现



public class StockServiceImpl implements IStockService{
    private IStockDao stockDao;
    private IAccountDao accountDao;

    public void setStockDao(IStockDao stockDao) {
        this.stockDao = stockDao;
    }

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

    @Override
    public void buyStock(int sid, double scount, int aid, double abalance) {
        boolean isBuy = true;
        stockDao.updateStock(sid,scount,isBuy);
        accountDao.updateAccount(aid,abalance,isBuy);
    }
    @Override
    public void sellStock(int sid, double scount, int aid, double abalance) {
        boolean isBuy = false;
        stockDao.updateStock(sid,scount,isBuy);
        accountDao.updateAccount(aid,abalance,isBuy);
    }
}



  4.编写applicationContext.xml引入架包

    (1)没有加入事务的xml文件



<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="database.properties"/>
    </bean>
    <!--配置jdbc数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="url" value="${jdbc.url}"></property>
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
    <!--注册jdbcTemplate-->
    <bean id="jbdcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--注册dao实现-->
    <bean id="accountDao" class="cn.bank.dao.impl.AccountDaoImpl">
        <property name="jdbcTemplate" ref="jbdcTemplate"/>
    </bean>
    <bean id="stockDao" class="cn.bank.dao.impl.StockDaoImpl">
        <property name="jdbcTemplate" ref="jbdcTemplate"/>
    </bean>
    <!--注册service实现-->
    <bean id="stockService" class="cn.bank.service.impl.StockServiceImpl">
        <property name="accountDao" ref="accountDao"/>
        <property name="stockDao" ref="stockDao"/>
    </bean>



    功能测试:



@Test
    public void buyStock(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        IStockService stockService = (IStockService) context.getBean("stockService");
        stockService.buyStock(1001,1000,1204,10000);
    }



配置Spring的声明式事务管理 spring 声明式事务_spring_04

配置Spring的声明式事务管理 spring 声明式事务_java_05

(此处没有关联股票价格)

   (2)加入异常测试


@Override
public void buyStock(int sid, double scount, int aid, double abalance) {
    boolean isBuy = true;
    stockDao.updateStock(sid,scount,isBuy);
    if (1==1) {
        int i = 5 / 0;
    }
    accountDao.updateAccount(aid,abalance,isBuy);
}


  报错:

配置Spring的声明式事务管理 spring 声明式事务_java_06

  处理结果:

 

配置Spring的声明式事务管理 spring 声明式事务_配置Spring的声明式事务管理_07

配置Spring的声明式事务管理 spring 声明式事务_bc_08

  在执行一次:

 

配置Spring的声明式事务管理 spring 声明式事务_java_09

配置Spring的声明式事务管理 spring 声明式事务_spring_10

  现在我们可以看到,在增加股票和减少余额中间产生异常之后,股票增加而余额没有减少,这种现在肯定是错误的。

  (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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--通过bean元素生命需要Spring创建的实例。该实例的类型通过class属性指定,
    并通过id属性为该实例制定一个名称,以便于访问-->
    <!--引入数据库配置文件-->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="database.properties"/>
    </bean>
    <!--配置jdbc数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="url" value="${jdbc.url}"></property>
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
    <!--注册jdbcTemplate-->
    <bean id="jbdcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--注册dao实现-->
    <bean id="accountDao" class="cn.bank.dao.impl.AccountDaoImpl">
        <property name="jdbcTemplate" ref="jbdcTemplate"/>
    </bean>
    <bean id="stockDao" class="cn.bank.dao.impl.StockDaoImpl">
        <property name="jdbcTemplate" ref="jbdcTemplate"/>
    </bean>
    <!--注册service实现-->
    <bean id="stockService" class="cn.bank.service.impl.StockServiceImpl">
        <property name="accountDao" ref="accountDao"/>
        <property name="stockDao" ref="stockDao"/>
    </bean>
    <!--引入事务平台管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--事务拦截处理:使用代理工厂-->
    <bean id="serviceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="target" ref="stockService"/>
        <property name="transactionManager" ref="transactionManager"/>
        <!--事务参数的设定-->
        <property name="transactionAttributes">
            <props>
                <prop key="buyStock">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
</beans>


  测试(修改getBean()方法的参数):


@Test
    public void buyStockTest(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        IStockService stockService = (IStockService) context.getBean("serviceProxy");
        stockService.buyStock(1001,1000,1204,10000);
    }


  异常发生,数据没有改变(是我们预期的结果,也是业务需要的):

配置Spring的声明式事务管理 spring 声明式事务_数据库_11

配置Spring的声明式事务管理 spring 声明式事务_数据库_12

配置Spring的声明式事务管理 spring 声明式事务_spring_10

    最后,去掉异常,保证事务管理下业务功能正常:

配置Spring的声明式事务管理 spring 声明式事务_java_14

配置Spring的声明式事务管理 spring 声明式事务_spring_15

配置Spring的声明式事务管理 spring 声明式事务_数据库_16

四:业务实现正常