• spring03-SpringJdbcTemplate模板技术和事务处理


    SpringJdbcTemplate

    Spring的JdbcTemplate是一个对JDBC的模板封装,它提供了一套JDBC的模板,能让我们写持久层代码时减少多余的代码,简化JDBC代码,使代码看起来更简洁。在介绍Spring的JdbcTemplate使用方法之前我们先来讨论一个问题,以下这是一段常见的往数据库写入数据的JDBC代码:

    public int jdbcInsert(Student student) throws SQLException {
    
        Connection connection = null;
    
        try {
            connection = dataSource.getConnection();
    
            String sql = "INSERT INTO student(sname,age,sex,address) VALUES (?,?,?,?)";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, student.getName());
            preparedStatement.setInt(2, student.getAge());
            preparedStatement.setString(3, student.getSex());
            preparedStatement.setString(4, student.getAddress());
    
            return preparedStatement.executeUpdate();
        } finally {
            connection.close();
        }
    }
    
    public int jdbcUpdate(Student student) throws SQLException {
    
        Connection connection = null;
    
        try {
            connection = dataSource.getConnection();
    
            String sql = "UPDATE student SET sname=?,age=?,sex=?,address=?";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, student.getName());
            preparedStatement.setInt(2, student.getAge());
            preparedStatement.setString(3, student.getSex());
            preparedStatement.setString(4, student.getAddress());
    
            return preparedStatement.executeUpdate();
        } finally {
            connection.close();
        }
    }
    
    
    • 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

    从如上的代码中,可以看到两个方法中基本99%的代码都是重复的,除了sql语句之外,都是重复的代码,重复的代码就是坏味道,会让我们的产生大量的冗余代码,不易于维护和修改,而且写起来还累。

    所以Spring提供的JdbcTemplate正是用来解决这个问题的,其实Spring的JDBCTemplate有点像DBUtils,但是有时候还没有DBUitls好用。这里来学习一下使用Spring的JdbcTemplate来玩一下CRUD,毕竟JdbcTemplate在实际开发中一般不会使用,通常都是使用Mybatis、Hibernate等成熟、优秀的数据持久层框架,不过还是得知道Spring有一个这样的jdbc模板类

    添加依赖

    spring核心包4+2 jdbc模板包2个

    
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-jdbcartifactId>
        <version>5.2.9.RELEASEversion>
    dependency>
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-txartifactId>
        <version>5.2.9.RELEASEversion>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    测试

    @Test
    public void test(){
        //构建数据源
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///test");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
    
    	//获取对象
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);    
        //创建表
        jdbcTemplate.execute("create table test01(name varchar(10) )");
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Spring配置数据源

    目标:将数据源和jdbcTemplate都交给Spring来管理:

    在applicationContext.xml中配置dataSource连接池和jdbcTemplate模版对象。

    spring内置数据源

    
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///test"/>
        <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class JdbcTempleTest {
        //注入jdbcTemplate
        @Autowired
        private JdbcTemplate jdbcTemplate;
        @Test
        public void test(){
            this.jdbcTemplate.execute("create table jdbctest05(name varchar(10))");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    dbcp数据源

    Apache commons-dbcp 需要导入dbcp包和 pool包

    添加依赖

    <dependency>
      <groupId>commons-dbcpgroupId>
      <artifactId>commons-dbcpartifactId>
      <version>1.4version>
    dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    
    <bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///test"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    bean>
    
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource2"/>
    bean>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class JdbcTempleTest {
    
        //注入jdbcTemplate
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        @Test
        public void test(){
            this.jdbcTemplate.execute("create table jdbctest06(name varchar(10))");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    C3P0 数据源

    <dependency>
      <groupId>com.mchangegroupId>
      <artifactId>c3p0artifactId>
      <version>0.9.5.2version>
    dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    
    <bean id="dataSource3" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql:///test"/>
        <property name="user" value="root"/>
        <property name="password" value="root"/>
    bean>
    
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource3"/>
    bean>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class JdbcTempleTest {
        //注入jdbcTemplate
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        @Test
        public void test(){
            this.jdbcTemplate.execute("create table jdbctest07(name varchar(10))");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    Druid数据源

    
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>druidartifactId>
        <version>1.2.3version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    
    <bean id="dataSource4" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///test"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
        
        <property name="maxActive" value="5"/>
        
        <property name="minIdle" value="1"/>
    bean>
    
    
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource4"/>
    bean>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class JdbcTempleTest {
        //注入jdbcTemplate
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        @Test
        public void test(){
            this.jdbcTemplate.execute("create table jdbctest07(name varchar(10))");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 相关配置

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F5402RTk-1664592948340)(assets/image-20211217000623540.png)]

    外部属性文件的配置

    • db.properties
    jdbc.driverClass=com.mysql.cj.jdbc.Driver
    jdbc.jdbcurl=jdbc:mysql:///test?serverTimezone=Asia/Shanghai
    jdbc.username=root
    jdbc.password=root
    
    • 1
    • 2
    • 3
    • 4
    • applicationContext.xml
    
    <context:property-placeholder location="classpath:db.properties"/>
    
    
    <bean id="dataSource4" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClass}"/>
        <property name="url" value="${jdbc.jdbcurl}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        
        <property name="maxActive" value="5"/>
        
        <property name="minIdle" value="1"/>
    bean>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    基于JdbcTemplate实现CURD

    数据库准备

    CREATE TABLE `t_book` (
      `id` int(11) NOT NULL,
      `name` varchar(255) DEFAULT NULL,
      `price` decimal(10,2) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    查询

    实体类

    @Data
    public class Book {
        private Integer id;
        private String name;
        private Double price;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    dao层

    /**
     * @Auther: yanqi
     * @Desc: 继承 JdbcDaoSupport类,父类中已注入JdbcTemplate对象
     */
    public class BookDao extends JdbcDaoSupport {
        /**
         * 查询所有
         */
        public List<Book> queryAll(){
            return super.getJdbcTemplate().query("select * from t_book", new BeanPropertyRowMapper<>(Book.class));
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    数据源

    
    <context:property-placeholder location="classpath:db.properties"/>
    
    
    <bean id="dataSource4" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClass}"/>
        <property name="url" value="${jdbc.jdbcurl}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    bean>
    
    
    <bean id="bookDao" class="cn.yanqi.dao.BookDao">
        <property name="dataSource" ref="dataSource4"/>
    bean>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • db.properties
    jdbc.driverClass=com.mysql.jdbc.Driver
    jdbc.jdbcurl=jdbc:mysql:///test
    jdbc.username=root
    jdbc.password=root
    
    • 1
    • 2
    • 3
    • 4
    • 测试
    /**
     * @Auther: yanqi
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class JdbcTemplateTest {
    
        @Autowired
        private BookDao bookDao;
    
        @Test
        public void test2(){
            List<Book> books = this.bookDao.queryAll();
            for(Book book : books){
                System.out.println(book);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    实现增加、删除、修改功能

    /**
     * 添加
     */
    public void addBook(Book book){
        String sql = "insert into t_book(id,name,price) values(null,?,?)";
        super.getJdbcTemplate().update(sql,book.getId(),book.getName(),book.getPrice());
    }
    
    /**
     * 删除
     */
    public void deleteBook(Integer id){
        String sql = "delete from t_book where id = ?";
        super.getJdbcTemplate().update(sql,id);
    }
    
    /**
     * 修改
     */
    public void updateBook(Book book){
        String sql = "update t_book set name = ? where id = ?";
        super.getJdbcTemplate().update(sql,book.getName(),book.getId());
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    Spring事务管理

    基于_XML的事务管理

    编写转账案例,引出事务问题

    • 数据库准备
    CREATE TABLE `t_account` (
      `id` int(11) DEFAULT NULL,
      `name` varchar(255) DEFAULT NULL,
      `money` double DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    spring-transaction

    • 添加依赖
       <dependencies>
    
        <dependency>
          <groupId>com.alibabagroupId>
          <artifactId>druidartifactId>
          <version>1.2.3version>
        dependency>
    
        <dependency>
          <groupId>mysqlgroupId>
          <artifactId>mysql-connector-javaartifactId>
          <version>5.1.47version>
        dependency>
    
        <dependency>
          <groupId>org.slf4jgroupId>
          <artifactId>slf4j-log4j12artifactId>
          <version>1.6.4version>
        dependency>
    
        <dependency>
          <groupId>log4jgroupId>
          <artifactId>log4jartifactId>
          <version>1.2.17version>
        dependency>
    
        <dependency>
          <groupId>org.springframeworkgroupId>
          <artifactId>spring-jdbcartifactId>
          <version>5.2.9.RELEASEversion>
        dependency>
    
        <dependency>
          <groupId>org.springframeworkgroupId>
          <artifactId>spring-aopartifactId>
          <version>5.2.9.RELEASEversion>
        dependency>
    
        <dependency>
          <groupId>org.springframeworkgroupId>
          <artifactId>spring-aspectsartifactId>
          <version>5.2.9.RELEASEversion>
        dependency>
    
        <dependency>
          <groupId>org.springframeworkgroupId>
          <artifactId>spring-contextartifactId>
          <version>5.2.9.RELEASEversion>
        dependency>
    
        <dependency>
          <groupId>org.springframeworkgroupId>
          <artifactId>spring-testartifactId>
          <version>5.2.9.RELEASEversion>
        dependency>
           
        <dependency>
          <groupId>junitgroupId>
          <artifactId>junitartifactId>
          <version>4.12version>
          <scope>runtimescope>
        dependency>
      dependencies>
    
    • 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
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • dao层
    public class AccountDao extends JdbcDaoSupport {
        public void out(String outName , double money){
            String sql = "update t_account set money = money - ? where name = ?";
            this.getJdbcTemplate().update(sql,money,outName);
        }
    
        public void in(String inName , double money){
            String sql = "update t_account set money = money + ? where name = ?";
            this.getJdbcTemplate().update(sql,money,inName);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • service层
    public class AccountService {
    
        private AccountDao accountDao;
        public void setAccountDao(AccountDao accountDao) {
            this.accountDao = accountDao;
        }
    
        public void tranfar(String outName , String  inName , double money){
    
            this.accountDao.out(outName,money);
    
            int a = 1/0;
    
            this.accountDao.in(inName,money);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • db.properties
    jdbc.driverClass=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql:///test
    jdbc.username=root
    jdbc.password=root
    
    • 1
    • 2
    • 3
    • 4
    • applicationContext.xml
    
    <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"
           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.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
    
        
        <context:property-placeholder location="classpath:db.properties"/>
    
        
        <bean id="dataSource4" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="${jdbc.driverClass}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
            
            <property name="maxActive" value="5"/>
            
            <property name="minIdle" value="1"/>
        bean>
    
        
        <bean id="accountDao" class="cn.yanqi.dao.AccountDao">
            <property name="dataSource" ref="dataSource4"/>
        bean>
    
        
        <bean id="accountService" class="cn.yanqi.service.AccountService">
            <property name="accountDao" ref="accountDao"/>
        bean>
    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
    • 测试
    @RunWith(SpringRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class AccountServiceTest {
    
        @Autowired
        private AccountService accountService;
    
        @Test
        public void tranfar() {
    
            this.accountService.tranfar("jack","rose",100);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    发现事务管理问题:没有事务的情况下,如果出现异常,则会转账不成功,数据异常。
    扩展:如果不配置事务,那么每一个数据库的操作都是单独的一个事务。
    
    • 1
    • 2

    加入事务

    • 添加tx事务约束
    
    <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:aop="http://www.springframework.org/schema/aop"
           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/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx.xsd">
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 事务控制
        
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource4"/>
        bean>
    
        
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                
                <tx:method name="transactionAccount"
                           isolation="DEFAULT"
                           propagation="REQUIRED"
                           timeout="-1"
                           rollback-for=""
                           no-rollback-for=""/>
                
                
            tx:attributes>
        tx:advice>
    
        
        <aop:config>
            
            <aop:pointcut id="txPointcut" expression="bean(*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
    • 测试
    /**
     * @Auther: yanqi
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class AccountServiceTest {
    
        @Autowired
        private AccountService accountService;
    
        @Test
        public void transactionAccount() {
            this.accountService.transactionAccount("jack","rose",100.0);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    遇到异常不回滚(相当于没有事务)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kb1d6f3J-1664592948342)(assets/image-20211217202707415.png)]

    事务的传播行为PropagationBehavior

    什么是事务的传播行为?

    一个事务调用了另 一个事务,如果出现错误,两个事务是否属于同一个事务

    有什么作用?

    事务传播行为用于解决两个被事务管理的方法互相调用问题

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JlTaNfFY-1664592948344)(assets/image-20211217202839587.png)]

    • 事务的传播行为的7种类型

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J1A4nxQU-1664592948345)(assets/image-20211217202857824.png)]

    • 主要分为三大类
    	PROPAGATION_REQUIRED(默认值)、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORY
    支持当前事务, A调用B,如果A事务存在,B和A处于同一个事务 。
    事务默认传播行为 REQUIRED。最常用的。
    
    	PROPAGATION_REQUIRES_NEW、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER 
    不会支持原来的事务 ,A调用B, 如果A事务存在, B肯定不会和A处于同一个事务。
    常用的事务传播行为:PROPAGATION_REQUIRES_NEW
    
    	PROPAGATION_NESTED
    嵌套事务 ,只对DataSourceTransactionManager有效 ,底层使用JDBC的SavePoint机制,允许在同一个事务设置保存点,回滚保存点
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    基于_注解声明式事务

    导入的依赖包跟xml方式一样

    pring-transactional-ann

    声明式事务

    /**
     * @Auther: yanqi
     */
    @Service
    // @Transactional //当前类都会被 事务管理
    public class AccountService {
    
        @Autowired
        private AccountDao accountDao;
    
        @Transactional //事务管理
        public void transactionAccount(String outName, String inName , Double money){
            this.accountDao.out(outName,money);
            int a = 1/0;
            this.accountDao.in(inName,money);
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • dao层
    /**
     * @Auther: yanqi
     * @Desc: 先用jdbcTemplate完成对数据库的操作
     */
    @Repository
    public class AccountDao extends JdbcDaoSupport {
    
    
        /**
         * 随便写一个set方法,注入DataSource,使用父数据源
         * @param dataSource
         */
        @Autowired
        public void setJdbcDaoSupport(DataSource dataSource){
            super.setDataSource(dataSource);
        }
    
        /**
         * 减钱
         */
        public void out(String name , Double money){
            String sql = "update t_account set money = money - ? where name = ?";
            super.getJdbcTemplate().update(sql,money, name);
        }
    
        /**
         * 加钱
         */
        public void in(String name , Double money){
            String sql = "update t_account set money = money + ? where name = ?";
            super.getJdbcTemplate().update(sql,money, name);
        }
    
    }
    
    
    • 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

    配置注解事务

    
    <context:component-scan base-package="cn.yanqi"/>
    
    
    <context:property-placeholder location="classpath:db.properties"/>
    
    
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    bean>
    
    
    
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    bean>
    
    
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 配置事务的定义属性信息,在注解中直接配置

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EpZrVRlh-1664592948346)(assets/image-20211217203126239.png)]

    • 优化配置

    配置注解驱动事务管理的时候,tx:annotation-driven/默认会自动查找并加载名字为transactionManager的事务管理器Bean,因此,当事务管理器的bean的名字为transactionManager 时,可以省略transaction-manager的属性

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pNV522gW-1664592948347)(assets/image-20211217203218262.png)]
    taSource">




    
    
    
    - **配置事务的定义属性信息,在注解中直接配置**
    
    [外链图片转存中...(img-EpZrVRlh-1664592948346)] 
    
    
    
    - **优化配置**
    
    >配置注解驱动事务管理的时候,默认会自动查找并加载名字为transactionManager的事务管理器Bean,因此,当事务管理器的bean的名字为transactionManager 时,可以省略transaction-manager的属性
    
    [外链图片转存中...(img-pNV522gW-1664592948347)]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    C++14读写锁demo-读写操作都在子线程中
    AJAX学习
    【IDEA】解决使用Terminal窗口按ESC键无法退出Vi的问题
    Spring Security 6.x 系列【68】 授权篇之基于注解 & 缓存的访问控制方案
    Maven Eclipse
    多模态论文阅读-LLaVA
    数据库的三范式及BC范式
    递归展示树状图/树状表格
    案例研究 | 玉湖冷链基于JumpServer实现管理安全一体化
    IPSec 协议族的理解
  • 原文地址:https://blog.csdn.net/zhangchen124/article/details/127132485