前言:
小伙伴们,大家好,我是狂奔の蜗牛rz,当然你们可以叫我蜗牛君,我是一个学习Java半年多时间的小菜鸟,同时还有一个伟大的梦想,那就是有朝一日,成为一个优秀的Java架构师。
这个Spring基础学习系列是用来记录我学习Spring框架基础知识的全过程 (这个系列是参照B站狂神的Spring5最新教程来写的,由于是之前整理的,但当时没有发布出来,所以有些地方可能有错误,希望大家能够及时指正!)
之后我将会以一天一更的速度更新这个系列,还没有学习Spring5框架的小伙伴可以参照我的博客学习一下;当然学习过的小伙伴,也可以顺便跟我一起复习一下基础。
最后,希望能够和大家一同进步吧!加油吧!少年们!
废话不多说,让我们开始今天的学习内容吧,今天我们来到了Spring基础学习的第十四站:Spring事务的实现方式!
14.1 Spring事务的实现方式
14.1.1 Spring事务的实现方式是什么?
事务这个概念是数据库层面的,Spring只是基于数据库中的事务进行了扩展,以及提供了一些让程序员能够更加方便操作的方式
Spring的事务管理分为两种方式,分别为编程式事务管理和声明式事务管理
- 编程式事务管理:即使用事务管理模板 (TransactionTemplate) 手动地管理事务,在实际开发中一般不使用,这里作为了解即可
- 声明式事务管理:是Spring默认的事务管理方式,需要在配置文件中定义数据源 (DriverManagerDataSource) 和事务管理器 (DataSourceTransactionManager),然后把事务管理器注入到事务代理工厂Bean (TransactionProxyFactoryBean) 生成代理,或者使用Spring AOP XML 方式 (<基于 tx / AOP 配置的声明式事务管理方式) 进行配置,也可以使用Spring AOP Annotation 方式 (即使用@Transactional注解实现声明式事务管理)
14.1.2 使用TransactionProxyFactoryBean方式
1.编写MySQL数据库脚本和引入相关资源依赖
1-1 编写MySQL数据库脚本
-- 创建数据库MyBatis,``用来防止与MySQL关键字发生冲突
Create Database `MyBatis`;
-- 使用MyBatis数据库
Use `MyBatis`;
-- 创建数据库表User
Create table `User`(
`id` int(10) not null primary key,
`name` varchar(30) default null,
`pwd` varchar(30) default null
)engine=InnoDB default charset=utf8;
-- 批量插入一些用户信息
Insert into `User`(`id`,`name`,`pwd`) values
(1,'周杰伦','zjl123456'),
(2,'方文山','fws123456'),
(3,'黄俊郎','hjl123456')
1-2 引入项目相关资源依赖
- 前提需要创建一个Maven项目,然后在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">
<parent>
<artifactId>spring-study</artifactId>
<groupId>com.kuang</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-10-mybatis</artifactId>
<!-- 导入资源依赖 -->
<dependencies>
<!-- mysql驱动资源依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- mybatis资源依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!-- spring资源依赖 -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<!-- spring要操作数据库,还需腰一个spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<!-- junit单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- log4j资源依赖 -->
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- aop织入资源依赖 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<!-- mybatis-spring资源依赖 -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.3</version>
</dependency>
<!-- lombok资源依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
</dependencies>
<!-- 在build中配置resources,来防止我们资源导出失败的问题 -->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
2.编写数据库配置文件和Mybatis核心配置文件
2-1 编写db.properties数据库配置文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456
2-2 编写mybatis-config.xml配置文件
<?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>
<!-- 设置标准日志输出 -->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!-- 使用别名:通过包起别名 -->
<typeAliases>
<package name="com.kuang.pojo"/>
</typeAliases>
</configuration>
3.编写User实体类和UserMapper接口
3-1 编写User实体类
package com.kuang.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data // 引入无参构造,get和set方法以及toString方法
@AllArgsConstructor // 引入有参构造
@NoArgsConstructor // 再次引入无参构造,防止引入有参构造时覆盖无参构造
public class User {
private int id; // 用户编号
private String name; // 用户名
private String pwd; // 密码
}
3-2 编写UserMapper接口
package com.kuang.mapper;
import com.kuang.pojo.User;
import java.util.List;
public interface UserMapper {
// 获取所有用户信息
public List<User> getUsers();
// 增加用户信息
public int insertUser(User user);
// 删除用户信息
public int deleteUser(int id);
// 修改用户信息
public int UpdateUser(User user);
}
4.编写UserMapper.xml映射文件和UserMapperImpl实现类
4-1 编写UserMapper.xml映射文件
- 在resources资源路径下创建与UserMapper相同包路径,存放UserMapper.xml映射文件
<?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">
<!--namespace=绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.kuang.mapper.UserMapper">
<!-- 查询所有用户信息 -->
<!-- 当通过包起别名后,resultType(结果类型)直接使用对应实体类名即可,不需要写全类名 -->
<select id="getUsers" resultType="user">
Select * from mybatis.user
</select>
<!-- 增加用户信息 -->
<insert id="insertUser" parameterType="com.kuang.pojo.User">
Insert into mybatis.user(id, name, pwd)
values(#{id} ,#{name}, #{pwd})
</insert>
<!-- 删除用户信息 -->
<delete id="deleteUser" parameterType="int">
Delete from mybatis.user where id = #{id}
</delete>
<!-- 修改用户信息 -->
<update id="UpdateUser" parameterType="com.kuang.pojo.User">
Update mybatis.user
set name = #{name}, pwd = #{pwd}
where id = #{id}
</update>
</mapper>
4-2 编写UserMapperImpl实现类
package com.kuang.mapper;
import com.kuang.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
import java.util.List;
public class UserMapperImpl implements UserMapper {
// 引入SqlSessionTemplate对象
private SqlSessionTemplate sqlSessionTemplate;
// 使用set方法动态注入SqlSessionTemplate对象
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
// 重写getUsers方法
public List<User> getUsers() {
// 获取UserMapper对象
UserMapper userMapper = sqlSessionTemplate.getMapper(UserMapper.class);
// 返回UserMapper对象的getUsers方法
return userMapper.getUsers();
}
}
为了节省篇幅,这里就不编写UserService类和UserServiceImpl实现类了
5.编写spring-dao.xml和ApplicationContext.xml配置文件
5-1 编写spring-dao.xml配置文件
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 1.关联数据库配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 2.配置DataSource数据源:读取数据库配置文件,这里使用的Spring默认的数据源JDBC -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 3.配置sqlSessionFactory工厂对象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 2.1 引用dataSource数据源 -->
<property name="dataSource" ref="dataSource"/>
<!-- 2.2 绑定Mybatis的核心配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 2.3 在核心配置文件中注册Mapper.xml文件 -->
<property name="mapperLocations" value="classpath*:com/kuang/mapper/*.xml"/>
</bean>
<!-- 4.配置SqlSessionTemplate模板对象 -->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<!-- 只能使用构造器注入sqlSessionFactory:因为它没有set方法 -->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<!-- 5.配置transactionManager事务管理器:依赖于dataSource数据源 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 6.生成代理类(userDaoProxy):让代理管理事务,依赖于事务管理类 -->
<bean id="userDaoProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!-- #6.1 提供事务管理器(transactionManager) -->
<property name="transactionManager" ref="transactionManager"/>
<!-- #6.2 配置目标类userMapper -->
<property name="target" ref="userMapper"/>
<!-- #6.3 提供UserMapper接口-->
<property name="proxyInterfaces" value="com.kuang.mapper.UserMapper"/>
<!-- #6.4 事务的详情配置,给事务定义对象(TransactionDefinition)进行赋值 -->
<property name="transactionAttributes">
<props>
<!-- 配置增强目标类的所有的方法(*表示所有),并且设置传播行为和隔离级别 -->
<prop key="*">PROPAGATION_REQUIRED,ISOLATION_REPEATABLE_READ</prop>
</props>
</property>
</bean>
</beans>
通过设置prop标签中的key属性,用来配置对目标类内的哪些方法进行增强
key表示方法名称,如果使用 “*”,表示所有的方法;如果使用get *,表示以get开头的方法
prop标签中的text文本按照固定的格式,编写事务详情及TransactionDefinition的内容
- 传播行为(propagation_required) 表示支持当前事务,如果没有将创建新事务
- 隔离级别(isolation_repeatable_read) 表示可重复读级别等,值之间使用逗号进行分隔
5-2 编写ApplicationContext.xml配置文件
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 在主配置文件中导入spring-dao.xml配置文件 -->
<import resource="spring-dao.xml"/>
<!-- 注入userMapperImpl实现类 -->
<bean id="userMapper" class="com.kuang.mapper.UserMapperImpl">
<property name="sqlSessionTemplate" ref="sqlSessionTemplate"/>
</bean>
</beans>
6.测试结果和优缺点总结
6-1 测试结果
- 编写MyTest测试类
package com.kuang.mapper;
import com.kuang.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class MyTest {
@Test
public void getUsers() {
// 读取上下文信息,获取Spring的IOC容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过Spring的IOC容器获取userDaoProxy代理对象的Bean信息
UserMapper userMapper = (UserMapper) context.getBean("userDaoProxy");
// 调用userMapper的getUsers方法。获取所有用户信息,然后进行遍历
for (User user : userMapper.getUsers()) {
// 打印用户信息
System.out.println(user);
}
}
}
- 测试结果
6-2 优缺点总结
优势:在代码中无须关注业务逻辑,而是交给Spring容器进行事务控制
缺点:配置文件过于臃肿,难以阅读
14.1.3 使用Spring AOP XML 方式
只需修改spring-dao.xml配置文件内容,其他与12.2.2中使用TransactionProxyFactoryBean方式一致
1.修改spring-dao.xml配置文件
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 1.关联数据库配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 2.配置DataSource数据源:读取数据库配置文件,这里使用的Spring默认的数据源JDBC -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 3.配置sqlSessionFactory工厂对象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 2.1 引用dataSource数据源 -->
<property name="dataSource" ref="dataSource"/>
<!-- 2.2 绑定Mybatis的核心配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 2.3 在核心配置文件中注册Mapper.xml文件 -->
<property name="mapperLocations" value="classpath*:com/kuang/mapper/*.xml"/>
</bean>
<!-- 4.配置SqlSessionTemplate模板对象 -->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<!-- 只能使用构造器注入sqlSessionFactory:因为它没有set方法 -->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<!-- 5.配置transactionManager事务管理器:依赖于dataSource数据源 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 6.结合AOP实现事务的织入:配置事务的通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 给方法配置事务,配置事务的传播特性:propagation -->
<tx:attributes>
<!-- #1 分别给插入、删除和修改用户的方法,配置propagation事务属性,其值为REQUIRED -->
<tx:method name="insert" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<!--#2 给查询用户方法设置只读-->
<tx:method name="select" read-only="true"/>
<!-- #3 给所有方法(*指所有方法)配置propagation事务属性,值也设为REQUIRED -->
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 7.配置业务切入 -->
<aop:config>
<!-- #7.1 设置切入点,增强com.kuang.mapper包及其子包下的类所有类型的全部方法 -->
<!-- 使用pointcut:设置切面通知执行的“地点”
使用expression:定义切入点表达式,execution(* com.kuang.mapper..*.*(..)) -->
<aop:pointcut id="txPointCut" expression="execution(* com.kuang.mapper..*.*(..))"/>
<!-- #7.2 执行环绕增加(把txAdvice(事务通知)与txPointCut(切入点的方法)相结合)-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
</beans>
2. 事务传播行为和切入点表达式
2-1 propagation事务传播行为
propagation有七种事务传播行为,默认是REQUIRED
- REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务,则是常见的选择
- SUPPORTS:支持当前事务,如果当前没有事务,就以非实物方式执行
- MANDATORY:支持当前事务,如果当前没有事务,就抛出异常
- REQUIRED_NEW:新建事务,如果当前存在事务,把当前事务挂起
- NO_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
- NEVER:以非事务方式执行,如果当前存在事务,则抛出异常
- NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务
2-2 expression切入点表达式
pointcut:表示切入点,即切面通知执行的“地点”
expression:表示定义切入点表达式,即execution(* com.kuang.mapper….(…))
-
execution():表达式主体
-
第一个 * 号:表示返回类型,*号表示所有的类型
-
com.kuang.mapper…:表示要拦截的包名,后面的两个.号表示当前包和当前包的所有子包
-
第二个 * 号:表示类名,*号表示所有的类
-
(…):最后这个*号表示方法名, * 号表示所有的方法,后面的()表示方法的参数,两个.号表示任何参数
3.测试结果和使用总结
3-1 测试结果
- 编写MyTest测试类
package com.kuang.mapper;
import com.kuang.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class MyTest {
@Test
public void getUsers() {
// 读取上下文信息,获取Spring的IOC容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过Spring的IOC容器获取UserMapper对象的Bean信息
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
// 调用userMapper的getUsers方法。获取所有用户信息,然后进行遍历
for (User user : userMapper.getUsers()) {
// 打印用户信息
System.out.println(user);
}
}
}
- 测试结果
3-2 优缺点总结
- Spring提供了基于tx / AOP 配置的声明式事务管理方式,也是实际开发中最常用的事务管理方式之一
- 与使用TransactionProxyFactoryBean方式相比,使用Spring AOP XML方式的实现就简单了许多
14.1.4 使用 Spring AOP Annotation 方式
1.修改spring-dao.xml配置文件
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 1.关联数据库配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 2.配置DataSource数据源:读取数据库配置文件,这里使用的Spring默认的数据源JDBC -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 3.配置sqlSessionFactory工厂对象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 2.1 引用dataSource数据源 -->
<property name="dataSource" ref="dataSource"/>
<!-- 2.2 绑定Mybatis的核心配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 2.3 在核心配置文件中注册Mapper.xml文件 -->
<property name="mapperLocations" value="classpath*:com/kuang/mapper/*.xml"/>
</bean>
<!-- 4.配置SqlSessionTemplate模板对象 -->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<!-- 只能使用构造器注入sqlSessionFactory:因为它没有set方法 -->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<!-- 5.配置transactionManager事务管理器:依赖于dataSource数据源 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 6.注册事务管理驱动 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
2. 修改UserMapperImpl实现类
package com.kuang.mapper;
import com.kuang.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
import java.util.List;
public class UserMapperImpl implements UserMapper {
// 引入SqlSessionTemplate对象
private SqlSessionTemplate sqlSessionTemplate;
// 使用set方法动态注入SqlSessionTemplate对象
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
// 使用@Transactional注解,设置事务传播行为,隔离级别和是否只读
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,readOnly = true)
// 重写getUsers方法
public List<User> getUsers() {
// 获取UserMapper对象
UserMapper userMapper = sqlSessionTemplate.getMapper(UserMapper.class);
// 返回UserMapper对象的getUsers方法
return userMapper.getUsers();
}
@Override
public int insertUser(User user) {
// 获取UserMapper对象
UserMapper userMapper = sqlSessionTemplate.getMapper(UserMapper.class);
// 返回UserMapper对象的insertUser方法
return userMapper.insertUser(user);
}
@Override
public int deleteUser(int id) {
// 获取UserMapper对象
UserMapper userMapper = sqlSessionTemplate.getMapper(UserMapper.class);
// 返回UserMapper对象的deleteUser方法
return userMapper.deleteUser(id);
}
@Override
public int UpdateUser(User user) {
// 获取UserMapper对象
UserMapper userMapper = sqlSessionTemplate.getMapper(UserMapper.class);
// 返回UserMapper对象的UpdateUser方法
return userMapper.UpdateUser(user);
}
}
3.编写测试类和测试结果
3-1 编写测试类
package com.kuang.mapper;
import com.kuang.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class MyTest {
@Test
public void getUsers() {
// 读取上下文信息,获取Spring的IOC容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 通过Spring的IOC容器获取UserMapper对象的Bean信息
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
// 调用userMapper的getUsers方法。获取所有用户信息,然后进行遍历
for (User user : userMapper.getUsers()) {
// 打印用户信息
System.out.println(user);
}
}
}
3-2 测试结果
4.使用总结
- 可以在Dao层或者Service层实现类上使用@Transcational注解,就可以开启事务,增删改查的每个方法中的所有SQL都会一个事务中执行,即要么都成功,要么都失败
- 在一个方法上加了@Transcational注解后,Spring会基于这个类生成一个代理对象,会将这个代理对象作为Bean
- 当在使用这个代理对象的方法时,如果这个方法上存在@Transcational注解,那么代理逻辑会先把事务的自动提交设置为false,然后再去执行原本的业务逻辑方法
- 如果执行业务逻辑的方法没有出现异常,那么代理逻辑就会将事务进行提交;如果执行业务逻辑方法出现了异常,那么则会将事务进行回滚
5.优缺点总结
- 使用@Transcational注解形式相比前两种方式,不需要去编写事务相关的繁琐的配置文件
- 只需要使用@Transcational注解,然后在注解中配置事务传播行为和隔离级别即可,开发效率得到了提升
好了,今天的有关Spring事务的实现方式的学习就到此结束啦,欢迎小伙伴们积极学习和讨论,喜欢的可以给蜗牛君点个关注,顺便来个一键三连,我们下期见,拜拜啦!
参考视频链接:https://www.bilibili.com/video/BV1WE411d7Dv(【狂神说Java】Spring5最新教程IDEA版通俗易懂)