spring boot基于注解的声明式事务配置详解

时间:2022-10-07 20:46:05

事务配置

1、配置方式一

1)开启spring事务管理,在spring boot启动类添加注解@EnableTransactionManagement(proxyTargetClass = true);等同于xml配置方式的 <tx:annotation-driven />(注意:1项目中只需配置一次,2需要配置proxyTargetClass = true)

2)在项目中需要添加事务的类或方法上添加注解@Transactional(建议添加在方法上),一般使用默认属性即可,若要使用事务各属性可查看spring事务官方文档了解

2、配置方式二(指定事务,需要多个事务管理器时用)

1)开启事务管理:创建多个事务,如下例子

?
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
@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
public class TransactionConfig implements TransactionManagementConfigurer{
    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;
    @Value("${spring.datasource.druid.url}")
    private String url;
    @Value("${spring.datasource.druid.username}")
    private String username;
    @Value("${spring.datasource.druid.password}")
    private String password;
    @Bean
    public DataSource dataSourceDb() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
    /**
     * 【作用】事务管理器<br>
     * 【说明】(无)
     * @param
     * @author Kalvin
     * @Date 2017/12/19 10:39
     */
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSourceDb());
    }
    // 创建事务管理器2
    @Bean(name = "txManager2")
    public PlatformTransactionManager txManager2(EntityManagerFactory factory) {
        return new JpaTransactionManager(factory);
    }
    /**
     * 【作用】如果没有指定事务,默认返回当前事务管理<br>
     * 【说明】(无)
     * @param
     * @author kkyc
     * @Date 2017/12/19 10:03
     */
    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return transactionManager();
    }
}

到这里已经成功整合好事务配置了,你只需要在使用的地方添加注解@Transactional即可,如果需要限定事务管理器,可使用@Transactional(“txManager2”)

spring boot事务(注解模式)

使用注解模式不需要配置文件,也不需要配置事务配置类或者方法,只需要使用“@Transcation”注解引入到相对应的位置即可实现事务回滚功能。

1.引入pom.xml

?
1
2
3
4
5
<!-- 事物 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
   </dependency>

2.在controller里面使用事务注解

因为service和接口层都是直接操作数据库的方法,一般需要多个操作或者循环的Controller才需要事务支持,如果是mybatis批量操作数据库语句也不需要事务

事务作用域一般常见的分成两种:

①定义在类上面 :所有的方法都支持事务

②定义在方法上 :只有该方法支持事务

?
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
64
package com.Transaction.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.Transaction.entity.Alarmtype;
import com.Transaction.mapper.AlarmtypeMapper;
import com.Transaction.service.AlarmtypeService;
@Controller
//@Transactional //事务级别,如果该类中同时操作多个方法,只要失败则全部回滚
public class AlarmtypeController {
 @Autowired
 AlarmtypeMapper alarmtypeMapper;
 
 @Autowired
 AlarmtypeService alarmtypeService;
 
 @RequestMapping("index")
 public synchronized String index(){
  //List<Alarmtype> list = alarmtypeMapper.getAlarmtypeList();
  List<Alarmtype> list = alarmtypeService.findAll();
  for (int i = 0; i < list.size(); i++) {
   System.out.println(list.get(i).getId()+"--"+list.get(i).getAlarmname());
  }
  return "index";
 }
 
 //批量插入
 @RequestMapping("addBatch")
 @ResponseBody
 @Transactional//对整个方法进行事务处理,方法体内只要有一个方法没执行成功则全部回滚
 public synchronized int addBatch(){
  Alarmtype alarmtype = new Alarmtype();
  Alarmtype updatealarmtype = new Alarmtype();
  updatealarmtype.setId(1);
  updatealarmtype.setAlarmname("修改前轮故障");
  alarmtypeMapper.updateAlarmtypeById(updatealarmtype);
  int result = 0;
  try {
   for (int i = 0; i < 5; i++) {
    if(i==2){
     //alarmname在数据库中长度不超过50,赋值超过50报异常 Data too long
     alarmtype.setAlarmname("测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试");
     alarmtype.setAlarmtypeid(i);
    }else{
     alarmtype.setAlarmname("测试"+i);
     alarmtype.setAlarmtypeid(i);
    }
    result = alarmtypeMapper.addAlarmtype(alarmtype);
   }
  }catch (Exception e) {
   e.printStackTrace();
  }
  return result;
 }
 
 @RequestMapping("test")
 @ResponseBody
 public synchronized String test(){ 
  return "test";
 }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/lkh1992/article/details/79021344