初学spring事务(一)

applicationContext.xml,spring声明式事务配置

<context:component-scan base-package="com.mazh.demo"/>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://locahost:3306/demo01"/>
        <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="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <tx:annotation-driven/>

pom.xml,jar包配置

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>5.2.12.RELEASE</spring.version>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>        
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
    </dependencies>
AccountService.java
package com.mazh.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

@SuppressWarnings("ALL")
@Service
public class AccountService {

    @Autowired
    JdbcTemplate jdbcTemplate;

    /**
     * 有异常自动回滚
     */
    @Transactional
    public void add1() {
        jdbcTemplate.execute("insert into account(name,money) values ('hangman',1000)");
        int i = 1 / 0;
    }

    /**
     * 捕获了异常而未抛出,事务失效
     */
    @Transactional
    public void add2() {
        jdbcTemplate.execute("insert into account(name,money) values ('hangman',1000)");
        try {
            int i = 1 / 0;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 捕获异常并抛出,事务回滚, ArithmeticException是RuntimeException的子类
     */
    @Transactional
    public void add3() {
        jdbcTemplate.execute("insert into account(name,money) values ('hangman',1000)");
        try {
            int i = 1 / 0;
        } catch (ArithmeticException e) {
            throw new ArithmeticException(e.getMessage());
        }
    }

    /**
     * 捕获异常并抛出(FileNotFoundException),事务失效,因为FileNotFoundException是Exception子类
     * Spring的事务管理默认是针对Error异常和RuntimeException异常以及其子类进行事务回滚
     */
    @Transactional
    public void add4() throws FileNotFoundException {
        jdbcTemplate.execute("insert into account(name,money) values ('hangman',1000)");
        try {
            new FileInputStream(new File(""));//java.io.FileNotFoundException
        } catch (FileNotFoundException e) {
            throw new FileNotFoundException();
        }
    }

    /**
     * jdbcTemplate空指针异常,spring事务对final、static修改的方法无法提供代理。
     * final修改的方法不能被重写,static修饰的方法属于类级别的,类的信息在编译期就知道了,并不支持运行期动态绑定
     */
    @Transactional
    public final void add5() {
        jdbcTemplate.execute("insert into account(name,money) values ('hangman',1000)");
        int i = 1 / 0;
    }

    /**
     * 非事务的方法调用内部的事务方法,事务失效,没有经过代理对象调用重写后的add7方法
     */
    public void add6() {
        jdbcTemplate.execute("insert into account(name,money) values ('hangman',2000)");
        add7();
    }

    @Transactional
    public void add7() {
        jdbcTemplate.execute("insert into account(name,money) values ('hangman',3000)");
        int i = 1 / 0;
    }

    /**
     * 两个事务方法之间的调用,事务生效.
     * 因为默认事务的传播是required,当前就事务就加入,没有就创建一个。所以从始至终是一个事务
     */
    @Transactional
    public void add8() {
        jdbcTemplate.execute("insert into account(name,money) values ('hangman',2000)");
        add9();
    }

    @Transactional
    public void add9() {
        jdbcTemplate.execute("insert into account(name,money) values ('hangman',3000)");
        int i = 1 / 0;
    }

    /**
     * 这种方式等同add8, 因为@Transactional(propagation = Propagation.REQUIRED)是默认的传播行为
     */
    @Transactional
    public void add10() {
        jdbcTemplate.execute("insert into account(name,money) values ('hangman',2000)");
        add11();
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void add11() {
        jdbcTemplate.execute("insert into account(name,money) values ('hangman',3000)");
        int i = 1 / 0;
    }

    /**
     * 事务回滚,REQUIRES_NEW这个属性表示不论当前是否存在事务,总是会新建一个事务,那么同一个事务回滚两个插入操作都回滚
     */
    @Transactional
    public void add12() {
        jdbcTemplate.execute("insert into account(name,money) values ('hangman',2000)");
        add13();
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void add13() {
        jdbcTemplate.execute("insert into account(name,money) values ('hangman',3000)");
        int i = 1 / 0;
    }

    /**
     * 事务回滚,真是颠覆程序员的认知啊,导致程序员畏手畏脚的罪魁祸首就是以讹传讹,不亲生实践
     * 并且int i = 1 / 0;在其中任意方法效果一致
     * @Transactional(propagation = Propagation.SUPPORTS)表示以非事务的方式运行
     */
//    @Transactional(propagation = Propagation.SUPPORTS)
    @Transactional
    public void add14() {
        jdbcTemplate.execute("insert into account(name,money) values ('hangman',2000)");
        add15();
//        int i = 1 / 0;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public void add15() {
        int i = 1 / 0;
        jdbcTemplate.execute("insert into account(name,money) values ('hangman',3000)");
    }


}
AccountServiceTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class AccountServiceTest {

    @Autowired
    private AccountService accountService;

    @Test
    public void test01() {
        accountService.add();
    }

}

account 表

CREATE TABLE `account` (
`id`  int(11) UNSIGNED NOT NULL AUTO_INCREMENT ,
`name`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`money`  int(11) NULL DEFAULT NULL ,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
AUTO_INCREMENT=2
ROW_FORMAT=COMPACT
;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值