zoukankan      html  css  js  c++  java
  • Spring 事务解决方案

    Spring 中的事务主要是利用 Aop 思想,简化事务的配置,可以通过 Java 配置也可以通过 XML 配置。

    我们通过一个转账操作来看下 Spring 中的事务配置。

    准备工作

    创建数据库

    CREATE DATABASE /*!32312 IF NOT EXISTS*/`test01` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;
    
    USE `test01`;
    
    /*Table structure for table `account` */
    
    DROP TABLE IF EXISTS `account`;
    
    CREATE TABLE `account` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
      `money` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
    
    /*Data for the table `account` */
    
    insert  into `account`(`id`,`username`,`money`) values (1,'zhangsan',1000),(2,'lisi',1000);
    

    配置 JdbcTemplate

    提供一个配置类,在配置类中配置 JdbcTemplate

    @Configuration
    public class JdbcConfig {
        
        @Bean
        DataSource dataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
            dataSource.setUsername("root");
            dataSource.setPassword("123456");
            dataSource.setUrl("jdbc:mysql:///test01");
            return dataSource;
        }
        
        @Bean
        JdbcTemplate jdbcTemplate() {
            return new JdbcTemplate(dataSource());
        }
    }
    

    数据持久层

    @Repository
    public class UserDao {
        
        @Autowired
        JdbcTemplate jdbcTemplate;
    
        public void addMoney(String username, Integer money) {
            jdbcTemplate.update("update account set money=money+? where username=?", money, username);
        }
    
        public void minMoney(String username, Integer money) {
            jdbcTemplate.update("update account set money=money-? where username=?", money, username);
        }
    }
    

    业务逻辑层

    @Service
    public class UserService {
        
        @Autowired
        UserDao userDao;
        
        public void updateMoney() {
            userDao.addMoney("zhangsan", 200);
            int i = 1 / 0;
            userDao.minMoney("lisi", 200);
        }
    }
    

    相关配置

    最后,在 XML 文件中,开启自动化扫描:

    <context:component-scan base-package="com.antoniopeng"/>
    
    <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
        <property name="url" value="jdbc:mysql:///test01?serverTimezone=Asia/Shanghai"/>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
    </bean>
    
    <bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    

    XML 配置

    XML 中配置事务一共分为三个步骤:

    1. 配置 TransactionManager

    <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    

    2. 配置事务要处理的方法

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="update*"/>
            <tx:method name="insert*"/>
            <tx:method name="add*"/>
            <tx:method name="delete*"/>
        </tx:attributes>
    </tx:advice>
    

    注意,一旦配置了方法名称规则之后,service 中的方法一定要按照这里的名称规则来,否则事务配置不会生效

    3. 配置 AOP

    <aop:config>
        <aop:pointcut id="pc1" expression="execution(* com.antoniopeng.hello.spring.service.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pc1"/>
    </aop:config>
    

    4. 测试

    @Before
    public void before() {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        jdbcTemplate = ctx.getBean(JdbcTemplate.class);
        userService = ctx.getBean(UserService.class);
    }
    
    @Test
    public void test1() {
        userService.updateMoney();
    }
    

    Java 配置

    如果要开启 Java 注解配置,在 XML 配置中添加如下配置:

    <tx:annotation-driven transaction-manager="transactionManager" />
    

    这行配置,可以代替下面两个配置:

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="update*"/>
            <tx:method name="insert*"/>
            <tx:method name="add*"/>
            <tx:method name="delete*"/>
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut id="pc1" expression="execution(* org.javaboy.service.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pc1"/>
    </aop:config>
    

    然后,在需要添加事务的方法上,添加 @Transactional 注解,表示该方法开启事务,当然,这个注解也可以放在类上,表示这个类中的所有方法都开启事务。

    @Service
    public class UserService {
        
        @Autowired
        UserDao userDao;
        
        @Transactional
        public void updateMoney() {
            userDao.addMoney("zhangsan", 200);
            int i = 1 / 0;
            userDao.minMoney("lisi", 200);
        }
    }
    

    本文发于:https://antoniopeng.com

  • 相关阅读:
    你不知道的javaScript笔记(7)
    你不知道的javaScript笔记(6)
    你不知道的javaScript笔记(5)
    你不知道的javaScript笔记(4)
    你不知道的javaScript笔记(3)
    你不知道的javaScript笔记(2)
    java 单链表反转
    Java找出两个链表的第一个公共节点
    Java产生死锁的一个简单例子
    Java 中Enum的使用与分析
  • 原文地址:https://www.cnblogs.com/antoniopeng/p/14274850.html
Copyright © 2011-2022 走看看