• 02-Sping事务实现之声明式事务基于XML的实现方式


    声明式事务之XML实现方式

    开发步骤

    第一步: 引入AOP相关的aspectj依赖

    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-aspectsartifactId>
      <version>6.0.0-M2version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    第二步: 编写dao层接口及其实现类

    public interface AccountDao {
        // 根据账号查询余额
        Account selectByActno(String actno);
        // 	更新账户信息
        int update(Account act);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    @Repository("accountDao")
    public class AccountDaoImpl implements AccountDao {
        @Resource(name = "jdbcTemplate")
        private JdbcTemplate jdbcTemplate;
    
        @Override
        public Account selectByActno(String actno) {
            String sql = "select actno, balance from t_act where actno = ?";
            Account account = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Account.class), actno);
            return account;
        }
    
        @Override
        public int update(Account act) {
            String sql = "update t_act set balance = ? where actno = ?";
            int count = jdbcTemplate.update(sql, act.getBalance(), act.getActno());
            return count;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    第三步: 编写Service接口及其实现类,这里就不再使用@Transactional注解而是基于XML配置的方式实现声明式事务

    @Service("accountService")
    public class AccountServiceImpl implements AccountService {
        @Resource(name = "accountDao")
        private AccountDao accountDao;
        @Override
        public void transfer(String fromActno, String toActno, double money) {
            // 查询转出账户的余额是否充足
            Account fromAct = accountDao.selectByActno(fromActno);
            if (fromAct.getBalance() < money) {
                throw new RuntimeException("余额不足!!!");
            }
            // 余额充足
            Account toAct = accountDao.selectByActno(toActno);
    
            // 将内存中两个对象的余额先修改
            fromAct.setBalance(fromAct.getBalance() - money);
            toAct.setBalance(toAct.getBalance() + money);
    
            // 数据库更新
            int count = accountDao.update(fromAct);
    
            // 模拟异常
            String s = null;
            s.toString();
    
            count += accountDao.update(toAct);
    
            if(count != 2) {
                throw new RuntimeException("转账失败,联系银行!");
            }
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    第四步: 在spring的配置文件中添加context,aop和tx的命名空间及其约束文件,然后配置数据源,JdbcTemplate,事务管理器,通知,切面

    标签描述
    tx:advice自定义一个事务通知
    tx:method配置事务通知作用的方法和事务的相关属性
    advice-ref引入自定义的通知
    
    <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.xsd
                               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.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.xsd">
        
        <context:component-scan base-package="com.powernode.bank"/>
    
        
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/spring6"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        bean>
    
        
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource"/>
        bean>
    
        
        <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
        bean>
    
        
        <tx:advice id="txAdvice" transaction-manager="txManager">
            
            <tx:attributes>
                
                <tx:method name="transfer" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
                
                <tx:method name="save*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
                <tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
                <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
                <tx:method name="modify*" propagation="REQUIRED" rollback-for="java.lang.Throwable"/>
                <tx:method name="query*" read-only="true"/>
                <tx:method name="select*" read-only="true"/>
                <tx:method name="find*" read-only="true"/>
                <tx:method name="get*" read-only="true"/>
            tx:attributes>
        tx:advice>
        
        
        <aop:config>
            
            <aop:pointcut id="txPointcut" expression="execution(* com.powernode.bank.service..*(..))"/>
            
            <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
        aop:config>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    第五步: 测试配置的事务通知能否对目标对象的目标方法起到事务控制的作用

    @Test
    public void testTransferXml(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        AccountService accountService = applicationContext.getBean("accountService", AccountService.class);
        try {
            accountService.transfer("act-001", "act-002", 10000);
            System.out.println("转账成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    string类
    Moonbeam成功续约新一轮的Polkadot插槽租赁期
    哪款蓝牙耳机音质最好?千元级别音质最好的蓝牙耳机
    30道高频Vue面试题快问快答
    3分钟带你认识腾讯云服务器CVM_一看就懂
    ARTS第6周T:设计模式——外观模式(Facade模式)
    计算机实战项目之 含文档+PPT+源码等]精品基于Uniapp+SSM实现的新闻APP演示实现的App
    python-持久化存储文件操作
    【Linux】环境基础开发工具使用(熟练使用必练)(学习复习兼顾)
    Node.js精进(10)——性能监控(下)
  • 原文地址:https://blog.csdn.net/qq_57005976/article/details/134243671