多个包就以逗号隔开,讲一下SpringBoot的事务管理,这个时候我来问一下大家,Spring事务管理的时候,尤其整合事务的时候,
效果没有出现,但是那时候可能没有人说,就过去了,我就专门研究了一下,没生效就是这个原因,我们会详细去讲一下SpringBoot
管理机制,主要是哪里出错了呢,是在多数据源的时候,整合事务出错了,为什么出错了呢,这个我们详细讲什么原因,其实在文档里面,
你们以后不要copy老版本的,整合多数据源的时候,你们一定要把什么加上去呢,不然他默认走的是第一个事务,事务就不生效,就是
这个原因,首先回顾一下基本的几个概念,第一个问题是Spring的事务,事务的一个分类,第二个是Spring事务的一个原理,那首先来
问大家一个问题,Spring事务的分类有哪些,这是最基本的,有声明式事务,还有编程时事务,那么在这边其实我说过的,Spring事务分类
里面,声明式事务的原理是什么,也是基于编程事务进来的,编程事务就是手动去commit,声明式事务是什么样的呢,是自己通过扫包,
要指定范围,那么在这边大家记住一点,这个Spring事务的原理是什么,事务的原理,通过AOP技术,通过环绕通知去拦截,进行拦截,
使用Spring事务的注意事项,是不要try,因为要将异常抛出给外层,Springboot整合事务,你觉得用注解好呢还是用其他的方式好呢,
基本上都是用注解版本的,因为你们基本上都是用注解的,那么在这个地方,SpringBoot里面默认已经帮你集成事务了,只要你在方法上
加上@Transactional注解就可以了,那么他默认的传播行为是什么,默认是required,默认是开启事务的,怎么样验证这个事务开启
成功了
http://localhost:8080/insertUser
{
"id":1,
"username":"leon",
"password":"123456",
"openid":"abcd",
"role":1
}
public void insertUser(User user) {
userMapper.insertUser(user);
int i = 1 / 0;
}
userMapper.insertUser(user)走完的时候,一旦加了@Transactional注解之后,他会不会提交到数据库去,就不会了,
所以我们可以知道什么呢,只要我加了@Transactional,事务开启成功的情况下,那么他应该怎么样呢,没有真正提交到数据库去,
只有当你这个方法执行完毕的情况下,才提交到数据库里面去,是不是这样的,这个我就不多说,当你一旦发生异常的情况下,
rollback回滚,是不是这样的,这个是比较基础的知识,我们先不加这个事务注解,这个时候我们打个断点,我们同样的道理,
自动提交数据库里面去,相当于没有事务管理,底层有一个AOP技术,方法之前就会被拦截,如果一旦你这边突然报错的情况下,
它会走到异常通知,然后进行回滚,万一你有很多方法都要加,也不要太在意这个事情,其实原理也比较简单,通过AOP技术,
如果他开头以insert,什么delete,方法就会被拦截,就被给你开启一个事务,这个原理你下去都可以去写,类似于一个
声明式事务就行了,那么我把它放到类上面,其实这样也不是很好,导致其他查询的也加了,你们不要觉得这个事务很麻烦,
事务与事务冲突的问题,传播行为,可能比不想用我这个事务的情况下,都要配置传播行为的,所以你不要觉得这样很麻烦,
做项目你会发现传播行为还是比较多的,默认@Transactional注解,已经开启了,不用加@Enable,Springboot整合任何框架
都so easy,整合Spring的事务特别麻烦,需要各种配置,还需要配置什么表达式,这个你加个注解就OK了,他自动帮你开启了,
你们可以点进去看一下是不是Spring的事务注解,肯定是的,但是你要知道,springboot2.0之后,他用的Spring的版本
都是Spring5.0版本,讲新特性的时候会谈到的
org.springframework.transaction.annotation.Transactional
回滚的时候是走的AOP里面的,不是手动的去回滚,他框架帮你封装好了,只要发生异常的情况下,我会在异常通知里面帮你做回滚,
注解原理
<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>
<groupId>com.learn</groupId>
<artifactId>springboot_mybatis01</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.12.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
</properties>
<dependencies>
<dependency>
<!-- 引入web模块 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot进行单元测试的模块 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 引入druid数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.8</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
<!-- 这个插件,可以将应用打包成一个可执行的jar包 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
#debug=true
#server.port=7900
#server.context-path=/boot02
logging.level.com.learn=trace
#logging.file=D:/springboot.log
logging.file=springboot.log
logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
logging.pattern.file=%d{yyyy-MM-dd} ==== [%thread] %-5level ==== %logger{50} ==== %msg%n
#spring.resources.static-locations=classpath:/hello,classpath:/learn
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/SpringCloud?useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
spring.datasource.maxWait=60000
mybatis.config-location=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
spring.application.name=springboot_mybatis01
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.learn.cloud.mapper.UserMapper">
<select id="getUserById" resultType="com.learn.cloud.entity.User">
select * from user_info where id = #{id}
</select>
<insert id="insertUser" parameterType="com.learn.cloud.entity.User" >
insert into user_info(id, username, password,openid,role) values(#{id}, #{username}, #{password}, #{openid}, #{role})
</insert>
</mapper>
package com.learn.cloud.mapper;
import com.learn.cloud.entity.User;
//@Mapper或者@MapperScan将接口扫描装配到容器中
//@Mapper
public interface UserMapper {
public User getUserById(Long id);
public void insertUser(User user);
}
package com.learn.cloud.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.learn.cloud.entity.User;
import com.learn.cloud.mapper.UserMapper;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User getUserById(Long id) {
User user = this.userMapper.getUserById(id);
return user;
}
@Transactional
public void insertUser(User user) {
userMapper.insertUser(user);
@SuppressWarnings("unused")
int i = 1 / 0;
}
}
package com.learn.cloud.entity;
public class User {
private Long id;
private String username;
private String password;
private String openid;
private Integer role;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public Integer getRole() {
return role;
}
public void setRole(Integer role) {
this.role = role;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + ", openid=" + openid
+ ", role=" + role + "]";
}
}
package com.learn.cloud.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.learn.cloud.entity.User;
import com.learn.cloud.service.UserService;
/**
* 测试Mybatis去整合SpringBoot
* @author Leon.Sun
*
*/
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/getUserById/{id}")
public User getUserById(@PathVariable Long id) {
return this.userService.getUserById(id);
}
@PostMapping("/insertUser")
public Map<String,Object> insertUser(@RequestBody User user) {
Map<String,Object> map = new HashMap<String,Object>();
try {
userService.insertUser(user);
map.put("msg", "success");
} catch (Exception e) {
e.printStackTrace();
map.put("msg", "fail");
}
return map;
}
}
package com.learn.cloud;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan(value="com.learn.cloud.mapper")
@SpringBootApplication
public class Mybatis01Application {
public static void main(String[] args) {
SpringApplication.run(Mybatis01Application.class, args);
}
}