什么是事务?
事务是我们进行数据库操作时最小的单位,在逻辑上的原则是要么都成功要么都失败。
需求: 用户转账操作
业务逻辑的实现: (1) 需要先从
A
账户中减去100
元,然后从B
账户中增加100
元,
此时就需要 事务的支持,而这个转账操作需要2条sql语句的支持, 这两条sql语句就是一个事务。
事务有4大特性:
事务的隔离级别:
第一步: 引入依赖
<dependences>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--spring 的 核心包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!--lombok 依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<!--面向切面编程-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<!--Spring的声明式事务管理-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<!--Spring测试包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!--Mysql 驱动连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!-- 阿里巴巴的 druid 连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
</dependences>
第二步: 去配置文件中,开启事务的管理
<?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:tx="http://www.springframework.org/schema/tx"
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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--开启包扫描-->
<context:component-scan base-package="com.atguigu"></context:component-scan>
<!--加载 jdbc 配置文件-->
<context:property-placeholder location="classpath*:jdbc.properties"></context:property-placeholder>
<!--注册数据源连接-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!--这个驱动可写可不写-->
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--注册 JDBC模板-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="druidDataSource"></property>
</bean>
<!--开启声明式事务-->
<tx:annotation-driven proxy-target-class="false" transaction-manager="transactionManager"></tx:annotation-driven>
<!--注册 事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入dataSources-->
<property name="dataSource" ref="druidDataSource"/>
</bean>
</beans>
第三步: 编写配置文件
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url= 自己的数据库地址
jdbc.username= 自己的用户名
jdbc.password= 自己的数据库密码
第四步: 创建业务层代码
public interface UserService {
void addUser();
}
package com.atguigu.service.impl;
import com.atguigu.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private JdbcTemplate jdbcTemplate;
// 开启事务注解
@Transactional
public void addUser(){
String sql = "INSERT INTO user values(null,?,?,?)";
jdbcTemplate.update(sql,"鸭小架",28,"女");
deleteUser();
}
@Transactional
public void deleteUser(){
String sql = "DELETE FROM user WHERE id = ?";
jdbcTemplate.update(sql,45);
// int a = 2/0;
}
}
第五步: 测试
// 自动加载配置文件
@ContextConfiguration("classpath:/spring.xml")
// 运行单元测试
@RunWith(SpringJUnit4ClassRunner.class)
public class TransactionalTest {
@Autowired
private UserService userService;
@Test
public void testTransactional(){
userService.addUser();
}
}
这个注解上加
@Transactional(propagation = Propagation.REQUIRED)
@Transactional(propagation = Propagation.REQUIRES_NEW)
■ 传播属性:
● REQUIRED :如果有事务在运行,当前的方法就在这个事务内运行,否则启动一个新的事务,并在自己的事务内运行。
● REQUIRES_NEW: 当前的方法必须启动新事务,并在它自己的事务内运行,如果有事务正在运行,应该将它挂起