Spring的7种事务传播行为分析实例(一)

本文通过一个SpringBoot项目实例,详细解析Spring的7种事务传播行为,包括新建/导入项目、配置、各层代码实现及测试。作者在回顾TransactionDefinition接口和Propagation枚举类后,决定通过实战加深理解,文中省略了具体代码,但提到了测试数据库连接和预览数据的步骤,后续将展示详细事务传播行为操作。
摘要由CSDN通过智能技术生成

今天任务不多,闲来没事的时候看到一篇关于事务传播机制的博客,里面除了对7种事务传播机制的介绍和讲解,还谈到了事务的传播机制定义在TransactionDefinition接口中,我们也可以通过枚举类Propagation类调用,然后正好也没事做,我就去看了一下TransactionDefinition接口和Propagation类的源码,看完之后发现里面就是对7种事务传播机制的定义还有几个获取事务的传播行为、隔离级别等的方法,想起面试那时候死记硬背事务的传播机制,到现在还是不知道原理,于是我就想做个demo实战一下,帮助我们进一步理解事务传播机制的原理。

这里关于7种事务传播机制我就不再重复介绍了,大家若有对定义还不清楚的可以自行百度,好了,话不多说,进入正题。

一、新建/导入项目

考虑到做一个小demo,我马上就想到SpringBoot,于是老规矩直接到SpringBoot官网下载一个基本的SpringBoot的demo,当然我们也可以创建一个SpringBoot项目,然后可以开始写实例了。

二、pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.6.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
        <!--添加Test依赖 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
        <!--添加Web依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--添加热部署依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <!--添加Swagger依赖 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.7.0</version>
        </dependency>
        <!--添加Swagger-UI依赖 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.7.0</version>
        </dependency>
		<!--添加postgresql依赖 -->
		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-rest</artifactId>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

注:Swagger是一个接口测试工具,我开始使用的数据库是postgresql,后来又改用oracle进行了测试,所以没有用这两个的不用添加它们相关的依赖。

三、application.yml/application.properties

配置数据库,我比较习惯用yml文件,配置如下:

spring:
  jpa:
    database: oracle
    show-sql: true
    hibernate:
          dialect: org.hibernate.dialect.OracleDialect
  datasource:
      url: jdbc:oracle:thin:@localhost:1521:orcl
      username: root
      password: root
      driverClassName: oracle.jdbc.driver.OracleDriver
  #spring:
  #  jpa:
  #    database: postgresql
  #    show-sql: true
  #    hibernate:
  #          ddl-auto: update
  #          dialect: org.hibernate.dialect.PostgreSQLDialect
  #    properties:
  #          hibernate:
  #            temp:
  #              use_jdbc_metadata_defaults: false
  #database:
  #  driverClassName: org.postgresql.Driver
  #datasource:
  # platform: postgres
  #  url: jdbc:postgresql://localhost:5432/mydb
  #  username: postgres
  #  password: 12345

四、创建controller层、service层、dao层以及vo

controller:

@RestController
@RequestMapping("/user/*")
public class UserController {

    private final static List<User> userList = new ArrayList<>();

    @Autowired
    UserRepository userRepository;

    @Autowired
    BusinessService businessService;

    @RequestMapping(value = "/save")
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
    public String doA() throws Exception {
        User user = new User();
        user.setId(6);
        user.setName("aaa");
        user.setPassword("bbb");
        userRepository.save(user);

        System.out.println("是否是代理调用,AopUtils.isAopProxy(businessService) : " + AopUtils.isAopProxy(businessService));
        System.out.println("是否是cglib类代理调用,AopUtils.isCglibProxy(businessService) : " + AopUtils.isCglibProxy(businessService));
        System.out.println("是否是jdk动态接口代理调用,AopUtils.isJdkDynamicProxy(businessService) : "
                + AopUtils.isJdkDynamicProxy(businessService));
        //使用代理调用方法doB()
        businessService.doB();

        int i = 1 / 0;// 抛出异常
        return "success";
    }

    @RequestMapping(value = "/userList", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public List<User> findAll() {
        final List<User> resultList = new ArrayList<>();
        final Iterable<User> all = userRepository.findAll();
        all.forEach(new Consumer<User>() {
            @Override
            public void accept(User user) {
                resultList.add(user);
            }
        });
        return resultList;
    }

    /*@RequestMapping(value = "/save", produces = MediaType.APPLICATION_JSON_VALUE)
    public void create() {
        try {
            doA();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }*/

    /*@Transactional(propagation = Propagation.REQUIRES_NEW,isolation=Isolation.DEFAULT,rollbackFor=Exception.class)
    public String doB() throws Exception {
        User user = new User();
        user.setId(7);
        user.setName("ccc");
        user.setPassword("ddd");
        userRepository.save(user);
        return "success";
    }*/
}

service:

public interface BusinessService {
    public String doB();
}
@Service("businessService")
public class BusinessServiceImpl implements BusinessService{
    @Autowired
    UserRepository userRepository;

    @Transactional(propagation = Propagation.REQUIRES_NEW,isolation= Isolation.DEFAULT,rollbackFor=Exception.class)
    public String doB() {
        User user = new User();
        user.setId(7);
        user.setName("ccc");
        user.setPassword("ddd");
        userRepository.save(user);
        return "success";
    }
}

dao:

@Repository
public interface UserRepository extends CrudRepository<User,Integer> {
}

vo:

@Entity
@Table(name = "USER_")
public class User implements Serializable {
    @Id
    @Column(name = "ID")
    private int id;
    @Column(name = "NAME")
    private String name;
    @Column(name = "PASSWORD")
    private String password;

    public User() {

    }

    public User(int id, String name, String password) {
        this.id = id;
        this.name = name;
        this.password = password;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

五、测试

到这里基本上案例已经写好了,已经减少了很多配置和代码了,先来看一下数据库:

启动SpringBoot项目,先测一下数据库连接有没有问题,在浏览器中输入路径http://localhost:8080/user/userList,如显示出数据说明配置没问题。

上面是准备工作,环境搭建好以后,后面将会对Spring的7种事务传播行为类型进行实例演示。未完待续。。。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值