2. 事务管理
2.1 回顾事务
- 什么是事务?
- 在数据库开发中,一组业务逻辑操作,要么全部成功,要么全部失败。
- 事务有什么特定?ACID
- 原子性:整体,原子不可分割的。整个操作被看成一个整体,要么成功,要么失败。
- 一致性:数据,事务操作的前后数据一致。
- 隔离性:并发,两个事务之间并发访问情况。
- 持久性:结果,事务一旦提交,不能回滚。
- 隔离有什么问题?
- 脏读:一个事务读到了另一个事务没有提交的数据。
- 不可重复读:一个事务读到了另一个事务已有提交的数据(update)。
- 幻读:一个事务读到了另一个事务已有提交的数据(insert)。
- 隔离级别有那些?
- 读未提交:存在3个问题(脏读、不可重复读、幻读)
- 读已提交:解决1个问题(脏读),存在2个问题(不可重复读、幻读)
- 可重复读:解决2个问题(脏读、不可重复读)、存在1个问题(幻读)
- 串行化:解决3个问题(脏读、不可重复读、幻读)–单事务
2.2 事务详解
- 研究Spring事务,需要学习事务管理平台管理器:
PlatformTransactionManager
- 在平台管理器中,通过
事务的定义
获得事务,从而进行事务提交或回滚操作。
- 在平台管理器中,通过
- 事务定义 TransactionDefinition 的详解:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qrFKyMEA-1633686524226)(assets/image-20211008093956217.png)]
- 传播行为:一个事务调用另一个事务,事务共享问题。
- PROPAGATION_REQUIRED,required:支持当前事务,如果没有事务,创建一个新的。
A 有事务,B使用A的事务。(支持当前事务)
A没有事务,B创建新的。()
- PROPAGATION_SUPPORTS,supports:支持当前事务,如果没有事务,以非事务执行。
A 有事务,B使用A的事务。(支持当前事务)
A没有事务,B以非事务执行。
- PROPAGATION_MANDATORY,mandatory:支持当前事务,如果没有事务,抛异常
A 有事务,B使用A的事务。(支持当前事务)
A没有事务,B抛异常。
- PROPAGATION_REQUIRES_NEW,requires_new:创建一个新事物,如果当前有事务,将挂起。
A 有事务,B创建新事务,同时挂起A事务。
A 没有事务,B创建新事务。
- PROPAGATION_NOT_SUPPORTED, not_supported:不支持当前事务,以非事务执行,如果有挂起
A 有事务,B以非事务执行,同时挂起A事务。
A 没有事务,B以非事务执行。
- PROPAGATION_NEVER, never:不支持当前事务,如果有抛异常。
A 有事务,B抛异常
A 没有事务,B以非事务执行。
PROPAGATION_NESTED, nested :嵌套事务,底层使用
savepoint
进行嵌套事务操作。 保存点允许回顾部分事务。
2.3 事务基本操作
-
步骤:
- 编写配置类:
- 使用DataSourceTransactionManager 将DataSource交给事务管理器。
- 开始事务管理:@EnableTransactionManagement
- 在业务service层进行事务管理:
- 通过 @Transactional进行事务管理
- 相当于进行
事务定义 TransactionDefinition
的描述
- 编写配置类:
-
配置类
package com.czxy.tx.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; /** * @author 桐叔 * @email liangtong@itcast.cn */ @Configuration @PropertySource("classpath:db.properties") @ComponentScan(basePackages = "com.czxy.tx") @EnableTransactionManagement public class SpringConfiguration { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; @Bean public DataSource dataSource() { DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setDriverClassName(driver); druidDataSource.setUrl(url); druidDataSource.setUsername(username); druidDataSource.setPassword(password); return druidDataSource; } @Bean public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }
-
业务类
package com.czxy.tx.service.impl; import com.czxy.tx.domain.Account; import com.czxy.tx.mapper.AccountMapper; import com.czxy.tx.service.AccountService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; /** * @author 桐叔 * @email liangtong@itcast.cn */ @Service @Transactional public class AccountServiceImpl implements AccountService { @Resource private AccountMapper accountMapper; @Override public void change(Integer outId, Integer inId, Float money) { //(id查询、修改金额,更新) //汇款人 -钱 Account outAccount = accountMapper.selectByPrimaryKey(outId); outAccount.setMoney( outAccount.getMoney() - money); accountMapper.updateByPrimaryKey(outAccount); // 错处了 int i = 1 / 0; //收款人 +钱 Account inAccount = accountMapper.selectByPrimaryKey(inId); inAccount.setMoney( inAccount.getMoney() + money); accountMapper.updateByPrimaryKey(inAccount); } }
2.4 事务高级操作
- @Transactional 注解可以描述事务定义,一般情况默认值最常用。
@Transactional(
readOnly = false,
timeout = -1,
isolation = Isolation.DEFAULT,
ropagation = Propagation.REQUIRED)
3 spring mvc 入门
3.1 入门案例:基于xml配置文件
3.1.1 目标
- 基于xml配置文件编写入门案例
3.1.2 步骤
- 步骤:
- 导入jar包
- 编写controller:业务处理入口,UserController
- 编写jsp页面:显示内容
- 编写核心配置文件:用于扫描controller
- 在web.xml中配置前端控制器:加载核心配置文件
- 将项部署到tomcat,启动并访问
http://localhost:8080/day11_mvc_xml/user/selectAll.action
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IWe3U9nS-1633686524229)(assets/image-20211008113313966.png)]
3.1.3 实现
-
导入jar包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6QU5b1MJ-1633686524231)(assets/image-20211008113413982.png)]
-
编写controller:业务处理入口,UserController
package com.czxy.mvc.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @author 桐叔 * @email liangtong@itcast.cn */ @Controller //将当前类添加到spring容器中 @RequestMapping("/user") public class UserController { //给当前类中所有功能,设置一个路径访问前缀 //最终访问路径 /user/selectAll.action @RequestMapping("/selectAll") //当功能方法,设置一个访问路径。 public String selectAll() { return "/list.jsp"; //jsp页面在web下 } }
-
编写jsp页面:显示内容
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cxdQeT3t-1633686524232)(assets/image-20211008113634459.png)]
-
编写核心配置文件:用于扫描controller
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"> <!-- 扫描注解包 --> <context:component-scan base-package="com.czxy.mvc.controller" /> </beans>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VksM9BCP-1633686524233)(assets/image-20211008113654712.png)]
-
在web.xml中配置前端控制器:加载核心配置文件
<!-- 设置前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KrAocp7Q-1633686524235)(assets/image-20211008113721273.png)]
-
将项部署到tomcat,启动并访问
总结:
1,Spring 事务管理有很多可以配置的选项,针对不同开发环境和要求,非常好用
2,整合Spring mvc也是相当的好用,省略Xml文件,直接代码进行配置,只需要讲扫描的包和类名注意一下就行了