1 Spring 事务管理
1.1 回顾
-
事务定义:在一组业务逻辑(ABCD)操作中,要么全部成功、要么全班失败。
-
事务特性:ACID
-
原子性:事务是一个不可分割的整体。
-
一致性:事务的操作前后,数据保持一致(数据保持完整)。
-
隔离性:两个事务的并发问题。
-
持久性:事务一旦提交,不能回滚。
-
-
并发访问问题(隔离问题)
-
脏读:一个事务读到了另一个事务没有提交的数据。
-
不可重复读:一个事务读到了另一个事务已经提交的数据(特指Update)。
-
虚读/幻读:一个事务读到了另一个事务已经提交的数据(特指Insert)。--纯理论
-
-
隔离级别:用于解决隔离问题。
-
读未提交:一个事务读到了另一个事务没有提交的数据。存在3个问题:脏读、不可重复读、幻读
-
读已提交:一个事务读到了另一个事务已经提交的数据。解决1个问题:脏读。存在2个问题:不可重复读、幻读。
-
可重复读:一个事务中,多次读取的数据是重复。解决2个问题:脏读、不可重复读。存在1个问题:幻读。
-
串行化:一次执行一个事务(单事务)。
-
1.2 基本代码
1.2.1 分析
1.2.2 环境搭建
-
项目:day050_sm_tx
-
添加坐标
<!--确定spring boot版本--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.5.RELEASE</version> <relativePath/> </parent> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <mybatis.starter.version>1.3.2</mybatis.starter.version> <mysql.version>5.1.32</mysql.version> </properties> <dependencies> <!--web开发启动器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--test 启动器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <!-- mybatis启动器 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis.starter.version}</version> </dependency> <!-- mysql驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--aop开发启动器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> </dependencies>
-
添加yml配置文件
spring:
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/day041?useUnicode=true&characterEncoding=utf8
username: root
password: '1234'
-
启动类
package com.czxy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ @SpringBootApplication public class TxApplication { public static void main(String[] args) { SpringApplication.run(TxApplication.class, args); } }
1.2.3 基本实现
-
JavaBean
package com.czxy.domain; import lombok.Data; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ @Data public class Account { private Integer id; private String name; private Integer money; }
-
AccountMapper接口
package com.czxy.mapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ @Mapper public interface AccountMapper { /** * 收款 * @param name * @param money */ @Select("update account set money=money+#{money} where name=#{name}") public void in(@Param("name") String name, @Param("money") int money); /** * 汇款 * @param name * @param money */ @Select("update account set money=money-#{money} where name=#{name}") public void out(@Param("name") String name, @Param("money") int money); }
-
AccountService接口
package com.czxy.service; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ public interface AccountService { /** * 转账 * @param outUser 汇款人 * @param inUser 收款人 * @param money 金额 */ public void transfer(String outUser, String inUser , Integer money); }
-
AccountServiceImpl实现类
package com.czxy.service.impl; import com.czxy.mapper.AccountMapper; import com.czxy.service.AccountService; import org.springframework.stereotype.Service; import javax.annotation.Resource; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ @Service public class AccountServiceImpl implements AccountService { @Resource private AccountMapper accountMapper; @Override public void transfer(String outUser, String inUser, Integer money) { //收款 accountMapper.in(inUser, money); //汇款 accountMapper.out(outUser, money); } }
-
测试类
package com.czxy; import com.czxy.service.AccountService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ @RunWith(SpringRunner.class) @SpringBootTest(classes = TxApplication.class) public class TestAccountService { @Resource private AccountService accountService; @Test public void testTransfer() { accountService.transfer("jack","rose", 100); System.out.println("转账成功"); } }
1.3 添加事务
1.3.1 基本使用【掌握 】
-
使用
@Tansactional
修饰方法,该方法Spring将进行事务管理 -
使用
@Tansactional
修饰类,该类中的所有方法Spring将进行事务管理
1.3.2 API详解
-
所有的默认值,都是最优选项,一般情况可以解决大部分问题。
1)超时时间
//单位:秒。默认值-1,表示不设置
@Transactional(timeout = -1)
2)是否只读
//只读事务,只能进行查询操作
//默认为false,表示不是只读,也就是可以进行增删改查操作。
@Transactional(readOnly = false)
3)隔离级别
//默认值为:Isolation.DEFAULT,根据数据库隔离级别的值确定
@Transactional(isolation = Isolation.READ_COMMITTED)
4)传播行为
-
传播行为:两个业务之间,是否共享事务。
-
传播行为共7种
前提:业务A和业务B 1.PROPAGATION_REQUIRED:required 必须 支持当前事务(执行B时,如果A有事务,B直接使用) 如果不存在,创建一个新的(执行B时,如果A没有事务,B直接创建一个新事物) 2.PROPAGATION_SUPPORTS: supports 支持 支持当前事务 如果不存在,以非事务执行(执行B时,如果A没有事务,B以非事务执行) 3.PROPAGATION_MANDATORY:mandatory 强制 支持当前事务 如果不存在,将抛异常(执行B时,如果A没有事务,B将抛异常) 4.PROPAGATION_REQUIRES_NEW:requires_new 必须新的 必须创建一个新事务(A没有事务,B创建新事物) 如果当前事务存在,将挂起(A有事务,把A事务挂起(暂停),B创建新事物) 5.PROPAGATION_NOT_SUPPORTED: not_supported 不支持 以非事务的方式执行(A没有事务,B没有事务) 如果当前事务存在,将挂起(A有事务,把A事务挂起(暂停),B没有事务) 6.PROPAGATION_NEVER: never 从不 以非事务的方式执行(A没有事务,B没有事务) 如果当前事务存在,将抛异常(A有事务,抛异常) 7.PROPAGATION_NESTED nested 嵌套 底层使用SavePoint进行嵌套事务
1.4 底层分析(了解)
1.4.1 分析
1.4.2 基本XML配置
-
配置
数据源
和事务管理器
-
配置通知/配置详情
-
将
事务详情
作用域目标类
,等效给类上添加注解
2.Spring MVC
2.1 概述
2.1.1 介绍
-
Spring MVC:由Spring提供,用于处理
表示层
的技术。与浏览器进行交互的。 -
对Servlet进行了抽取和封装。
2.1.2 实现方式
-
方式1:请求转发
-
方式2:json方式【掌握】
2.2 入门案例
2.2.1 环境搭建
-
项目:day050_spring_mvc
-
坐标:web
<!--确定spring boot版本--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.5.RELEASE</version> <relativePath/> </parent> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <!--web开发启动器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
-
核心配置:application.yml
-
启动类
package com.czxy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ @SpringBootApplication public class MvcApplication { public static void main(String[] args) { SpringApplication.run(MvcApplication.class, args); } }
2.2.2 编写控制器
package com.czxy.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
import java.util.List;
/**
* @author 桐叔
* @email liangtong@itcast.cn
* @description
*/
@RestController //加入到Spring容器 + 响应json数据
@RequestMapping("/demo") //给当前类绑定路径
public class HelloController {
@RequestMapping("/hello") //给方法绑定的路径
public String hello() {
return "入门案例";
}
@RequestMapping("/hello2")
public List<String> hello2() {
return Arrays.asList("a","b","c","1","3","2");
}
}
2.3 postman / swagger
2.3.1 postman
2.3.2 swagger
-
swagger 用于自动生成请求接口的工具。
1)基本使用
-
导入坐标
<properties> <swagger.version>2.7.0</swagger.version> </properties> <dependencies> <!--swagger2--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${swagger.version}</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>${swagger.version}</version> </dependency> </dependencies>
-
拷贝配置类
2)高级使用(订制)
-
给类添加一些修饰注解
-
让访问接口更好看
2.4 常见注解
-
@RestController :用于修饰控制器类,作用:加入到Spring容器 + 响应json数据,底层有2个注解组合
-
@Controller:加入到Spring容器
-
@ResponseBody:响应json数据
-
-
@RequestMapping:给
类/方法
绑定访问路径的@RequestMapping(value="请求路径", method=请求方式) 请求方式取值:RequestMethod.GET/POST/PUT/DELETE //get请求 @RequestMapping(value="请求路径", method=RequestMethod.GET) //简写 @GetMapping("请求路径") //post请求 @RequestMapping(value="请求路径", method=RequestMethod.POST) //简写 @PostMapping("请求路径") //put请求 @RequestMapping(value="请求路径", method=RequestMethod.PUT) //简写 @PutMapping("请求路径") //delete请求 @RequestMapping(value="请求路径", method=RequestMethod.DELETE) //简写 @DeleteMapping(""请求路径"")
-
入门案例
package com.czxy.controller; import io.swagger.annotations.Api; import org.springframework.web.bind.annotation.*; import java.util.Arrays; import java.util.List; /** * @author 桐叔 * @email liangtong@itcast.cn * @description */ @RestController //加入到Spring容器 + 响应json数据 @RequestMapping("/demo") //给当前类绑定路径 @Api(tags = "入门程序接口",description = "这个Swagger入门程序的接口,提供基本CRUD操作") public class HelloController { //@RequestMapping(value = "/hello", method = RequestMethod.GET) //给方法绑定的路径,请求方式为get @GetMapping("/hello") public String hello() { return "入门案例"; } //@RequestMapping("/hello2") @PostMapping("/hello2") public List<String> hello2() { return Arrays.asList("a","b","c","1","3","2"); } }