本文主要介绍Spring中的事务相关知识:
1、熟悉事务管理的三个核心接口
2、了解Spring事务的两种方式
3、掌握基于XML和注解的事务使用
PlatformTransactionManage接口是Spring平台提供的平台事务管理器,主要用于管理事务。该接口中主要包含3个事务操作方法。
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.45version>
<scope>runtimescope>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.9version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.5version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>1.3.1version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
<version>1.7.25version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.0.8.RELEASEversion>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.8.13version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.0.8.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.0.8.RELEASEversion>
<scope>testscope>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.22version>
<scope>providedscope>
dependency>
dependencies>
CREATE TABLE `account` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`balance` decimal(10, 0) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `account` VALUES (1, 10000);
INSERT INTO `account` VALUES (2, 0);
package cn.simplelife.mapper;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
/**
* @ClassName AccountMapper
* @Description
* @Author simplelife
* @Date 2022/11/23 15:34
* @Version 1.0
*/
public interface AccountMapper {
void addBalance(@Param("inId") Long inId, @Param("amount") BigDecimal amount);
void subtractBalance(@Param("outId") Long outId, @Param("amount") BigDecimal amount);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.simplelife.mapper.AccountMapper">
<update id="addBalance">
UPDATE account
SET balance=balance + #{amount}
WHERE id = #{inId}
update>
<update id="subtractBalance">
UPDATE account
SET balance=balance - #{amount}
WHERE id = #{outId}
update>
mapper>
package cn.simplelife.domain;
import lombok.Data;
import java.math.BigDecimal;
/**
* @ClassName Account
* @Description
* @Author simplelife
* @Date 2022/11/23 15:15
* @Version 1.0
*/
@Data
public class Account {
private Long id;
private BigDecimal balance;
}
<?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>
<!--配置别名-->
<typeAliases>
<package name="cn.simplelife.domain"/>
</typeAliases>
<!--关联mapper-->
<mappers>
<mapper resource="cn/simplelife/mapper/*.xml"/>
</mappers>
</configuration>
package cn.simplelife.service;
import java.math.BigDecimal;
/**
* @ClassName IAccountService
* @Description
* @Author simplelife
* @Date 2022/11/23 17:09
* @Version 1.0
*/
public interface IAccountService {
void transfer(Long outId, Long inId, BigDecimal amount);
}
package cn.simplelife.service.impl;
import cn.simplelife.mapper.AccountMapper;
import cn.simplelife.service.IAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
/**
* @ClassName IAccountServiceImpl
* @Description
* @Author simplelife
* @Date 2022/11/23 17:10
* @Version 1.0
*/
@Service
public class IAccountServiceImpl implements IAccountService {
@Autowired
private AccountMapper accountMapper;
@Override
public void transfer(Long outId, Long inId, BigDecimal amount) {
accountMapper.subtractBalance(outId, amount);
System.out.println(10 / 0);
accountMapper.addBalance(inId, amount);
}
}
<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:tx="http://www.springframework.org/schema/tx"
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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.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">
<context:component-scan base-package="cn.simplelife.*"/>
<context:property-placeholder location="classpath:db.properties"/>
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${password}"/>
bean>
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="druidDataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
bean>
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.simplelife.mapper"/>
bean>
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="druidDataSource"/>
bean>
<tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager">
<tx:attributes>
<tx:method name="*"/>
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut id="txPoint" expression="execution(* cn.simplelife.service.impl.*ServiceImpl.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/>
aop:config>
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
beans>
import cn.simplelife.service.IAccountService;
import cn.simplelife.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.math.BigDecimal;
/**
* @ClassName SqlSessionFactoryTest
* @Description
* @Author simplelife
* @Date 2022/11/23 15:26
* @Version 1.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SqlSessionFactoryTest {
@Autowired
private IAccountService iAccountService;
@Test
public void getSqlSessionTest() {
System.out.println(MybatisUtils.getSqlSession());
iAccountService.transfer(1L, 2L, new BigDecimal("100"));
}
}
<?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:tx="http://www.springframework.org/schema/tx"
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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.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">
<!--配置Ioc 和 Di注解解析器-->
<context:component-scan base-package="cn.simplelife.*"/>
<!-- 关联db.properties-->
<context:property-placeholder location="classpath:db.properties"/>
<!--配置数据源-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${password}"/>
</bean>
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="druidDataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.simplelife.mapper"/>
</bean>
<!--配置事务管理器-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="druidDataSource"/>
</bean>
<!--开启事务注解支持-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
</beans>
添加注解
package cn.simplelife.service.impl;
import cn.simplelife.mapper.AccountMapper;
import cn.simplelife.service.IAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
/**
* @ClassName IAccountServiceImpl
* @Description
* @Author simplelife
* @Date 2022/11/23 17:10
* @Version 1.0
*/
@Service
public class IAccountServiceImpl implements IAccountService {
@Autowired
private AccountMapper accountMapper;
@Override
@Transactional
public void transfer(Long outId, Long inId, BigDecimal amount) {
accountMapper.subtractBalance(outId, amount);
System.out.println(10 / 0);
accountMapper.addBalance(inId, amount);
}
}