文章目录

前言一、事务的特性(ACID)二、事务的隔离级别三、spring中的事务平台事务管理器.事务定义ISOLation_XXX:**事务隔离级别.**PROPAGATION_XXX:**事务的传播行为**.

事务状态

关系:

四、使用XML文件配置事务1、 搭建环境2、 配置及业务编写3、 测试

五、使用注解形式进行事务开发总结

前言

事务是逻辑上的一组操作的集合,要么全部成功,要么全部失败。在实际的业务场景中,事务的应用场景范围很广泛,例如转账,订单,支付等

一、事务的特性(ACID)

事务有四大特性:

原子性:事务不可分割一致性:事务执行的前后,数据完整性保持一致.隔离性:一个事务执行的时候,不应该受到其他事务的打扰持久性:一旦结束,数据就永久的保存到数据库.

二、事务的隔离级别

在实际的开发中,可能会出现以下几种由数据操作引起的异常情况: 如果不考虑隔离性:

脏读:一个事务读到另一个事务未提交数据不可重复读:一个事务读到另一个事务已经提交数据(update)导致一个事务多次查询结果不一致虚读:一个事务读到另一个事务已经提交数据(insert)导致一个事务多次查询结果不一致

事务存在几种隔离级别:

未提交读:以上情况都有可能发生。已提交读:避免脏读,但不可重复读,虚读是有可能发生。可重复读:避免脏读,不可重复读,但是虚读有可能发生。串行化:避免以上所有情况.

三、spring中的事务

后端分层开发中,事务应用于Service层中。spring提供了事务管理API

平台事务管理器.

PlatformTransactionManager

getTransaction(TransactionDefinition definition) :开启事务rollback(TransactionStatus status) :回滚事务commit(TransactionStatus status) :提交事务

Spring为不同的持久化框架提供了不同PlatformTransactionManager接口实现

使用Spring JDBC或iBatis 进行持久化数据时使用(重点)

org.springframework.jdbc.datasource.DataSourceTransactionManager

使用Hibernate进行持久化数据时使用

org.springframework.orm.hibernate.HibernateTransactionManager

使用JPA进行持久化时使用

org.springframework.orm.jpa.JpaTransactionManager

当持久化机制是Jdo时使用

org.springframework.jdo.JdoTransactionManager

使用一个JTA实现来管理事务,在一个事务跨越多个资源时必须使用

org.springframework.transaction.jta.JtaTransactionManager

事务定义

TransactionDefinition

ISOLation_XXX:事务隔离级别.

ISOLATION_DEFAULT:默认级别. Mysql --> repeatable_read | Oracle -->> read_commited 级别如下:

ISOLATION_READ_UNCOMMITTED : 读未提交ISOLATION_READ_COMMITTED : 读已提交ISOLATION_REPEATABLE_READ :可重复读ISOLATION_SERIALIZABLE :串行化

PROPAGATION_XXX:事务的传播行为.

事务的传播行为是用来解决实际开发中的问题 传播行为是指:解决业务层调用事务的关系。

PROPAGATION_REQUIRED: 支持当前事务,如果不存在 就新建一个

A,B 如果A有事务,B使用A的事务,如果A没有事务,B就开启一个新的事务.(A,B是在一个事务中。)

PROPAGATION_SUPPORTS: 支持当前事务,如果不存在,就不使用事务

A,B 如果A有事务,B使用A的事务,如果A没有事务,B就不使用事务.

PROPAGATION_MANDATORY: 支持当前事务,如果不存在,抛出异常

A,B 如果A有事务,B使用A的事务,如果A没有事务,抛出异常.

PROPAGATION_REQUIRES_NEW: 如果有事务存在,挂起当前事务,创建一个新的事务

A,B 如果A有事务,B将A的事务挂起,重新创建一个新的事务.(A,B不在一个事务中.事务互不影响.)

PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果有事务存在,挂起当前事务

A,B 非事务的方式运行,A有事务,就会挂起当前的事务.

PROPAGATION_NEVER: 以非事务方式运行,如果有事务存在,抛出异常 PROPAGATION_NESTED: 如果当前事务存在,则嵌套事务执行

基于SavePoint技术. A,B A有事务,A执行之后,将A事务执行之后的内容保存到SavePoint.B事务有异常的话,用户需要自己设置事务提交还是回滚.

常用:(重点) PROPAGATION_REQUIRED PROPAGATION_REQUIRES_NEW PROPAGATION_NESTED

事务状态

TransactionStatus

是否有保存点 是否是一个新的事务 事务是否已经提交

关系:

关系:PlatformTransactionManager通过TransactionDefinition设置事务相关信息管理事务,管理事务过程中,产生一些事务状态,状态由TransactionStatus记录。

四、使用XML文件配置事务

spring支持声明式事务管理,只需要配置文件,不需要额外的编写代码 演示如下:

1、 搭建环境

创建account表并插入两条数据

CREATE TABLE `account` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`money` double DEFAULT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

INSERT INTO `account` VALUES ('1', '1000');

INSERT INTO `account` VALUES ('2', '1000');

新建项目略 导入pom.xml依赖

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">

4.0.0

com.wmj

SpringTX

1.0-SNAPSHOT

8

8

org.springframework

spring-context

5.3.24

org.springframework

spring-jdbc

5.3.24

org.aspectj

aspectjweaver

1.9.9.1

org.springframework

spring-tx

5.3.24

org.mybatis

mybatis

3.5.11

org.mybatis

mybatis-spring

2.0.7

mysql

mysql-connector-java

8.0.31

com.alibaba

druid

1.2.9

org.projectlombok

lombok

1.18.24

log4j

log4j

1.2.17

junit

junit

4.13.2

test

2、 配置及业务编写

配置mybatis-config.xml

PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

"https://mybatis.org/dtd/mybatis-3-config.dtd">

配置日志

log4j.rootLogger=DEBUG, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

配置数据源

db.username = 帐号

db.password = 密码

db.url = jdbc:mysql:///库名?serverTimezone=Asia/Shanghai&characterEncoding=UTF8

db.driverClassName = com.mysql.cj.jdbc.Driver

搭建后端业务代码

控制层

package com.wmj.controller;

import com.wmj.service.TestService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

/**

* --效率,是成功的核心关键--

*

* @Author lzl

* @Date 2023/2/13 16:04

*/

@Controller

public class TestController {

@Autowired

private TestService service;

public void testTx(Integer id1,Integer id2,Double money){

service.transferMoney(id1,id2,money);

}

}

业务层接口及其实现类

package com.wmj.service;

/**

* --效率,是成功的核心关键--

*

* @Author lzl

* @Date 2023/2/13 16:10

*/

public interface TestService {

void transferMoney(Integer id1, Integer id2, Double money);

}

package com.wmj.service.impl;

import com.wmj.mapper.TestMapper;

import com.wmj.service.TestService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

/**

* --效率,是成功的核心关键--

*

* @Author lzl

* @Date 2023/2/13 16:11

*/

@Service

public class TestServiceImpl implements TestService {

@Autowired

private TestMapper mapper;

@Override

public void transferMoney(Integer id1, Integer id2, Double money) {

mapper.dmoney(id1,money);

int a = 1/0;

mapper.amoney(id2,money);

}

}

持久层接口及其xml数据访问

package com.wmj.mapper;

import org.apache.ibatis.annotations.Param;

import org.springframework.stereotype.Repository;

/**

* --效率,是成功的核心关键--

*

* @Author lzl

* @Date 2023/2/13 16:12

*/

@Repository

public interface TestMapper {

Integer dmoney(@Param("id1") Integer id1, @Param("money") Double money);

Integer amoney(@Param("id2") Integer id2, @Param("money") Double money);

}

PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

update account set money = money - #{money} where id = #{id1}

update account set money = money + #{money} where id = #{id2}

配置spring核心配置文件application.xml

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/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

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd">

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

propagation="REQUIRED" read-only="false" />

id="txPc" />

3、 测试

package com.test;

import com.wmj.controller.TestController;

import org.junit.Test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

/**

* --效率,是成功的核心关键--

*

* @Author lzl

* @Date 2023/2/13 16:02

*/

public class Demo1 {

@Test

public void testTX(){

ClassPathXmlApplicationContext applicationContext =

new ClassPathXmlApplicationContext("application.xml");

TestController controller = (TestController)applicationContext.getBean("testController");

controller.testTx(1,2,200.00);

}

}

执行结果: 当没有遇到异常时,转账能正常执行,不在演示,此处演示当遇到异常时的事务效果 代码执行前数据库:

当遇到异常,代码终止执行,此时数据库

转账并没有进行提交,此时说明我们的事务配置成功!

五、使用注解形式进行事务开发

spring给我们提供了事务注解开发的方式,大大减少了代码编写,十分方便

创建项目配置基本与上方相同,我们将application.xml内容进行修改如下:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

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/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">

将业务实现类改造如下:

package com.wmj.service.impl;

import com.wmj.mapper.AccountMapper;

import com.wmj.service.AccountService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Isolation;

import org.springframework.transaction.annotation.Propagation;

import org.springframework.transaction.annotation.Transactional;

/**

* @Transactional 配置事务

* 可以写在类上,也可以写在方法上

*/

//@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,readOnly = false)

@Service

package com.wmj.service.impl;

import com.wmj.mapper.TestMapper;

import com.wmj.service.TestService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

/**

* --效率,是成功的核心关键--

*

* @Author lzl

* @Date 2023/2/13 16:11

*/

/**

* @Transactional 配置事务

* 可以写在类上,也可以写在方法上

*/

//@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,readOnly = false)

@Service

public class TestServiceImpl implements TestService {

@Autowired

private TestMapper mapper;

@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,readOnly = false)

@Override

public void transferMoney(Integer id1, Integer id2, Double money) {

mapper.dmoney(id1,money);

int a = 1/0;

mapper.amoney(id2,money);

}

}

测试略

总结

本次主要记录了spring的事务支持,及其两种开发方式。再会!!!

精彩文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: