• 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);
                }
            });
        }
    
    }
  • 相关阅读:
    20165334 第十三周选做
    20165334 实验五 网络编程与安全
    ### 20165334 —— 第十二周MySort(选作)
    2018-2019-1 20165227 20165228 20165237 实验一 开发环境的熟悉
    2018-2019-1 20165228 《信息安全系统设计基础》第四周学习总结
    2018-2019-1 20165228《信息安全系统设计基础》第三周课上测试
    2018-2019-1 20165228 《信息安全系统设计基础》第三周学习总结
    2018-2019-1 20165228 《信息安全系统设计基础》缓冲区溢出漏洞实验报告
    2018-2019-1 20165228 《信息安全系统设计基础》第二周学习总结
    2018-2019-1 20165228 苏祚堃《信息安全系统设计基础》第一周学习总结
  • 原文地址:https://www.cnblogs.com/xl118/p/6791771.html
Copyright © 2020-2023  润新知