Spring事务
事务(Transaction)是面向关系型数据库(RDBMS)企业应用程序的重要组成部分,用来确保数据的完整性和一致性。
事务了解 :MySQL学习记录 事务篇
Spring 实现声明式事务管理主要有 2 种方式:
- 基于 XML 方式的声明式事务管理
- 通过 Annotation 注解方式的事务管理
事务管理接口
Spring 的事务管理 :PlatformTransactionManager、TransactionDefinition 是事务主要核心接口
PlatformTransactionManager接口
该接口用于管理事务。其主要用于完成事务的提交、回滚,及获取事 务的状态信息
public interface PlatformTransactionManager extends TransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
void commit(TransactionStatus var1) throws TransactionException;
void rollback(TransactionStatus var1) throws TransactionException;
}
返回 | 抽象方法 | 说明 |
---|---|---|
TransactionStatus | getTransaction(@Nullable TransactionDefinition var1) | 获取事务的状态信息 |
void | commit(TransactionStatus var1) | 提交事务 |
void | rollback(TransactionStatus var1) | 回滚事务 |
TransactionDefinition接口
该接口主要获取事务相关信息的作用
public interface TransactionDefinition {
....
default int getPropagationBehavior() {
return 0;
}
default int getIsolationLevel() {
return -1;
}
default int getTimeout() {
return -1;
}
default boolean isReadOnly() {
return false;
}
@Nullable
default String getName() {
return null;
}
....
}
返回 | 抽象方法 | 说明 |
---|---|---|
int | getPropagationBehavior() | 获取事务的 传播行为 |
int | getIsolationLevel() | 获取事务的 隔离级别 |
int | getTimeout() | 获取事务的 超时时间 |
boolean | isReadOnly() | 获取事务是否 只读 |
String | getName() | 获取事务的 名称 |
属性说明
传播行为值 | 说明 |
---|---|
PROPAGATION_MANDATORY | 支持当前事务,如果不存在当前事务,则引发异常 |
PROPAGATION_NESTED | 如果当前事务存在,则在嵌套事务中执行 |
PROPAGATION_NEVER | 不支持当前事务,如果当前事务存在,则引发异常 |
PROPAGATION_NOT_SUPPORTED | 不支持当前事务,始终以非事务方式执行 |
PROPAGATION_REQUIRED | 默认传播行为,支持当前事务,如果不存在,则创建一个新的 |
PROPAGATION_REQUIRES_NEW | 创建新事务,如果已经存在事务则暂停当前事务 |
PROPAGATION_SUPPORTS | 支持当前事务,如果不存在事务,则以非事务方式执行 |
xml应用
主要配置组件(.xml)
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- <tx:method name="insert*" propagation="REQUIRED"/>-->
<!-- <tx:method name="add*" propagation="REQUIRED"/>-->
<!-- <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>-->
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<!-- aop编写,让Spring自动对目标生成代理,需要使用AspectJ的表达式 -->
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.service..*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt" />
</aop:config>
应用前提:
添加依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
实体类:(Student)
package com;
public class Student {
int id ;
String name;
int age;
public Student() {
}
public Student(int id , String name , int age) {
this.id = id;
this.name = name;
this.age = age;
}
public Student(String name , int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
StudentDao类:(信息交互类)
package com.dao;
import com.Student;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
public class StudentDao extends JdbcDaoSupport {
/**
* 添加数据
* @param student 学生类封装
* @return 更变条数
*/
public int insert(Student student) {
if (student == null) {
return 0;
}
String sql = "insert into student(name,age) value(?,?)";
return this.getJdbcTemplate().update(sql,student.getName(),student.getAge());
}
//其他业务操作省略
····
}
StudentService类:(业务处理类)
package com.service;
import com.Student;
import com.dao.StudentDao;
public class StudentService {
private StudentDao studentDao;
public void setStudentDao(StudentDao studentDao) {
this.studentDao = studentDao;
}
public int insert(Student student){
int a = studentDao.insert(student);
System.out.println("(1)添加成功 数据: " + student + "\t影响条目:"+a);
int aa = 1/0; //制造异常
student.setAge(student.getAge()+1);
int b = studentDao.insert(student);
System.out.println("(2)添加成功 数据: " + student + "\t影响条目:"+a);
return a+b;
}
}
Spring 容器配置:(.xml文件)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<!-- XML 配置数据源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbcUrl"
value="jdbc:mysql://192.168.6.129:3306/test?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false"/>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- 配置jdbc模板-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 类注入应用-->
<bean id="studentDao" class="com.dao.StudentDao">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<bean id="studentService" class="com.service.StudentService">
<property name="studentDao" ref="studentDao"/>
</bean>
<!-- 事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 事务触发方法 以及 事务处理方式-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- <tx:method name="insert*" propagation="REQUIRED"/>-->
<!-- <tx:method name="add*" propagation="REQUIRED"/>-->
<!-- <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>-->
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<!-- aop编写,让Spring自动对目标生成代理,需要使用AspectJ的表达式 -->
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.service..*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt" />
</aop:config>
</beans>
测试:
@Test
public void test_XML(){
ApplicationContext ac = new ClassPathXmlApplicationContext("SpringConfig.xml");
StudentService service = (StudentService) ac.getBean("studentService");
//在studentService类 会异常回滚
int number = service.insert(new Student("李四" , 33));
System.out.println("number : " + number);
}
Annotation应用
主要组件
@Transactional
@Transactional常用属性
属性名 | 说明 |
---|---|
propagation | 配置 事务传播行为 |
isolation | 配置 事务隔离级别 |
readOnly | 配置 事务是否只读 |
timeout | 配置 事务超时事件(单位: s) |
应用前提:
-
注册加载驱动
<tx:annotation-driven transaction-manager="txManager"/>
-
应用方法需要添加
@Transactional
注解
实体类:(Student)
package com;
public class Student {
int id ;
String name;
int age;
public Student() {
}
public Student(int id , String name , int age) {
this.id = id;
this.name = name;
this.age = age;
}
public Student(String name , int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
StudentDao类:(信息交互类)
package com.dao;
import com.Student;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
public class StudentDao extends JdbcDaoSupport {
/**
* 添加数据
* @param student 学生类封装
* @return 更变条数
*/
public int insert(Student student) {
if (student == null) {
return 0;
}
String sql = "insert into student(name,age) value(?,?)";
return this.getJdbcTemplate().update(sql,student.getName(),student.getAge());
}
//其他业务操作省略
····
}
StudentService类:(业务处理类)
package com.service;
import com.Student;
import com.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class StudentService {
//注入类
@Autowired
private StudentDao studentDao;
//事务配置
@Transactional(propagation = Propagation.REQUIRED , rollbackFor = {Exception.class})
public int insert(Student student){
int a = studentDao.insert(student);
System.out.println("(1)添加成功 数据: " + student + "\t影响条目:"+a);
int aa = 1/0; //制造异常
student.setAge(student.getAge()+1);
int b = studentDao.insert(student);
System.out.println("(2)添加成功 数据: " + student + "\t影响条目:"+a);
return a+b;
}
}
Spring 容器配置:(.xml文件)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!-- XML 配置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--驱动加载-->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<!--连接数据库的url . 本次连接 test库-->
<property name="url" value="jdbc:mysql://192.168.6.129/test"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- 配置jdbc模板-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--必须使用数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--扫描包-->
<context:component-scan base-package="com"/>
<!-- 事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 事务应用-->
<bean id="studentDao" class="com.dao.StudentDao">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
<!--以注解形式应用-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
测试:
@Test
public void test_Annotation() {
ApplicationContext ac = new ClassPathXmlApplicationContext("SpringConfig_Annotation.xml");
StudentServic service = (StudentService) ac.getBean("");
int number = service_annotation.insert(new Student("赵六" , 34));
System.out.println("number : " + number);
}