zoukankan      html  css  js  c++  java
  • Spring事物管理--编程式

    以简单的转账金额为例:

    1、数据库(建表、插入数据)

    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 VALUE('1','aaa',1000);
    INSERT INTO account VALUE('2','bbb',1000);
    INSERT INTO account VALUE('3','ccc',1000);

    2、引入jar包

    3、创建jdbc.properties文件(设置连接数据库参数)

    jdbc.driverClass=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql:///xl
    jdbc.username=root
    jdbc.password=123456

    4、创建Dao持久层

    (1)、创建AccountDao接口

    //转账案例持久层接口    
    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);
        
    }

    (2)创建AccountDaoImpl实现类

    继承JdbcDaoSupport类,从而获取jdbc模板,以便对数据库进行各种操作

    //转账案例持久层实现类
    public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
    
        /**
         * @param out    :转出账号
         * @param money    :转账金额 
         */
        @Override
        public void outMoney(String out, Double money) {
            String sql = "update account set money = money - ? where name = ?";
            this.getJdbcTemplate().update(sql,money,out);
        }
    
        /**
         * @param in    :转入账号
         * @param money    :转账金额
         */
        @Override
        public void inMoney(String in, Double money) {
            String sql = "update account set money = money + ? where name = ?";
            this.getJdbcTemplate().update(sql,money,in);
        }
    }

    5、创建Service业务层

    (1)、创建AccountService接口

    //转账案例业务层接口
    public interface AccountService {
    
        /**
         * @param out    :转出账号
         * @param in    :转入账号
         * @param money    :转账金额
         */
        public void transfer(String out,String in,Double money);
    }

    (2)、创建AccountServiceImpl实现类(用Dao持久层的转出、转入的方法)

    //转账案例业务层实现类
    public class AccountServiceImpl implements AccountService {
    
        //注入转账的Dao
        @Resource
        private AccountDao accountDao;
        /**
         * @param out    :转出账号
         * @param in    :转入账号
         * @param money    :转账金额 
         */
        @Override
        public void transfer(final String out, final String in, final Double money) {
                    accountDao.outMoney(out, money);
                    accountDao.inMoney(in, money);
                }
            });
        }
    
    }

    6、配置applicationContext.xml文件

    引入jdbc.properties文件,在c3p0连接池中引用jdbc中的数据库连接参数,并将连接池设为持久层实现类的属性

    <?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-4.0.xsd
           http://www.springframework.org/schema/context 
           http://www.springframework.org/schema/context/spring-context-4.0.xsd
           http://www.springframework.org/schema/tx 
           http://www.springframework.org/schema/tx/spring-tx-2.0.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>
            <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="cn.xl.spring.demo1.AccountServiceImpl">
         </bean>
         
         <!-- 配置持久层类 -->
         <bean id="accountDao" class="cn.xl.spring.demo1.AccountDaoImpl">
             <property name="dataSource" ref="dataSource"></property>
         </bean>
    </beans>

    7、测试类

    //转账测试类
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class SpringDemo1 {
    
        @Resource(name="accountService")
        private AccountService accountService;
        
        @Test
        public void demo1(){
            accountService.transfer("bbb", "aaa", 200d);
        }
    }

    注:以上可以步骤可实现基本的数据业务操作,但存在一定的风险性,即钱转出了,对方却没有收到,这就坑爹了,

    所以要使用事物管理,即:将转出与转入两个操作放到一个事物管理中,那么转出和转入要么一起成功,要么一起失败,

    不会存在一个成功,另一个失败的情况!

    8、在applicationContext.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-4.0.xsd
           http://www.springframework.org/schema/context 
           http://www.springframework.org/schema/context/spring-context-4.0.xsd
           http://www.springframework.org/schema/tx 
           http://www.springframework.org/schema/tx/spring-tx-2.0.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>
            <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="cn.xl.spring.demo1.AccountServiceImpl">
         </bean>
         
         <!-- 配置持久层类 -->
         <bean id="accountDao" class="cn.xl.spring.demo1.AccountDaoImpl">
             <property name="dataSource" ref="dataSource"></property>
         </bean>
         
         <!-- 配置事物管理 器-->
         <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
             <property name="dataSource" ref="dataSource"></property>
         </bean>
         
         <!-- 配置事物管理的模板:sping为了简化事物管理的代码而提供的类 -->
         <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
             <property name="transactionManager" ref="transactionManager"></property>
         </bean>
    </beans>

    此处把事物管理器设为事物管理模板的属性,因为事务管理模板使用更加方便、简洁

    9、在AccountServiceImpl类中的两个持久层操作之间加入一个异常,以达到在不使用事物管理的情况下,两个数据业务操作不能够同步

    即:添加  int i = 1/0;

    还要注入事物管理模板类TransactionTemplate,调用execute方法,该方法有一个参数:TransactionCallback<T>事物回滚接口,而抽象类TransactionCallbackWithoutResult实现了TransactionCallback接口,并且自定义了doInTransactionWithoutResult方法,

    最后把我们要执行的操作都放到doInTransactionWithoutResult中,即:被同一个事物管理

    //转账案例业务层实现类
    public class AccountServiceImpl implements AccountService {
    
        //注入转账的Dao
        @Resource
        private AccountDao accountDao;
        //注解式注入事物管理模板
        @Resource
        private TransactionTemplate transactionTemplate;
        /**
         * @param out    :转出账号
         * @param in    :转入账号
         * @param money    :转账金额 
         */
        @Override
        public void transfer(final String out, final String in, final Double money) {
            transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    //把业务操作放入内部类中----在一个事物里面(同成功,同失败)
                    accountDao.outMoney(out, money);
                    int i = 1/0;
                    accountDao.inMoney(in, money);
                }
            });
        }
    
    }
  • 相关阅读:
    台州 OJ 3847 Mowing the Lawn 线性DP 单调队列
    洛谷 OJ P1417 烹调方案 01背包
    快速幂取模
    台州 OJ 2649 More is better 并查集
    UVa 1640
    UVa 11971
    UVa 10900
    UVa 11346
    UVa 10288
    UVa 1639
  • 原文地址:https://www.cnblogs.com/xl118/p/6791771.html
Copyright © 2011-2022 走看看