当前位置: 首页 > article >正文

Spring-事务学习

spring事务

1. 什么是事务?

事务其实是一个并发控制单位,是用户定义的一个操作序列,这些操作要么全部完成,要不全部不完成,是一个不可分割的工作单位。事务有 ACID 四个特性,即:

在这里插入图片描述

  1. 原子性(Atomicity):事务中的所有操作,或者全部完成,或者全部不完成,是一个不可分割的工作单元。
  2. 一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。
  3. 隔离性(Isolation):多个事务之间是独立的,不相互影响的。

​ 数据库允许多个并发事务同时对数据进行读写和修改, 隔离性可以防止多个事务并发执行时由于交叉执行而导致的数据的不一致。事物分为不同的隔离级别。

  • 读未提交
  • 读已提交
  • 可重复读(数据库的默认的事物隔离级别)
  • 串行化
  1. 持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

为了解释清楚这个问题,我们举个简单的例子:银行里树哥要给小黑转 1000 块钱,这时候会有两个必要的操作:

  1. 将树哥的账户余额减少 1000 元。
  2. 将小黑的账户余额增加 1000 元。

这两个操作,要么一起都完成,要么都不完成。如果其中某个成功,另外一个失败,那么就会出现严重的问题。而我们要保证这个操作的原子性,就必须通过 Spring 事务来完成,这就是 Spring 事务存在的原因。

如果你深入了解过 MySQL 事务,那么你应该知道:MySQL 默认情况下,对于所有的单条语句都作为一个单独的事务来执行。我们要使用 MySQL 事务的时候,可以通过手动提交事务来控制事务范围。Spring 事务的本质,其实就是通过 Spring AOP 切面技术,在合适的地方开启事务,接着在合适的地方提交事务或回滚事务,从而实现了业务编程层面的事务操作。

2. spring 事物的三大基础设施

1. PlatformTransactionManager 事务管理器接口

package org.springframework.transaction;

import org.springframework.lang.Nullable;

public interface PlatformTransactionManager extends TransactionManager {

	// 获取事务
	TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException;

    // 提交事务
	void commit(TransactionStatus status) throws TransactionException;

	// 事务回滚
	void rollback(TransactionStatus status) throws TransactionException;

}

2. TransactionDefinition 定义事务的属性

package org.springframework.transaction;

import org.springframework.lang.Nullable;

public interface TransactionDefinition {

	int PROPAGATION_REQUIRED = 0;

	int PROPAGATION_SUPPORTS = 1;

	int PROPAGATION_MANDATORY = 2;

	int PROPAGATION_REQUIRES_NEW = 3;

	int PROPAGATION_NOT_SUPPORTED = 4;

	int PROPAGATION_NEVER = 5;


	int PROPAGATION_NESTED = 6;

	int ISOLATION_DEFAULT = -1;

	int ISOLATION_READ_UNCOMMITTED = 1;  // same as java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;

	int ISOLATION_READ_COMMITTED = 2;  // same as java.sql.Connection.TRANSACTION_READ_COMMITTED;

	int ISOLATION_REPEATABLE_READ = 4;  // same as java.sql.Connection.TRANSACTION_REPEATABLE_READ;


	int ISOLATION_SERIALIZABLE = 8;  // same as java.sql.Connection.TRANSACTION_SERIALIZABLE;

	/**
	 * Use the default timeout of the underlying transaction system,
	 * or none if timeouts are not supported.
	 */
	int TIMEOUT_DEFAULT = -1;


	/**
	 * Return the propagation behavior.
	 */
	default int getPropagationBehavior() {
		return PROPAGATION_REQUIRED;
	}

	/**
	 * Return the isolation level.
	 */
	default int getIsolationLevel() {
		return ISOLATION_DEFAULT;
	}

	/**
	 * Return the transaction timeout.
	 * @return the transaction timeout
	 */
	default int getTimeout() {
		return TIMEOUT_DEFAULT;
	}

	/**
	 * Return whether to optimize as a read-only transaction.
	 */
	default boolean isReadOnly() {
		return false;
	}

	/**
	 * Return the name of this transaction. Can be {@code null}.
	 * <p>This will be used as the transaction name to be shown in a
	 * transaction monitor, if applicable (for example, WebLogic's).
	 * <p>In case of Spring's declarative transactions, the exposed name will be
	 * the {@code fully-qualified class name + "." + method name} (by default).
	 * @return the name of this transaction ({@code null} by default}
	 * @see org.springframework.transaction.interceptor.TransactionAspectSupport
	 * @see org.springframework.transaction.support.TransactionSynchronizationManager#getCurrentTransactionName()
	 */
	@Nullable
	default String getName() {
		return null;
	}


	static TransactionDefinition withDefaults() {
		return StaticTransactionDefinition.INSTANCE;
	}
}

3. TransactionStatus Spring事务 或者 Spring事务的状态

package org.springframework.transaction;

import java.io.Flushable;

public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {

	/**
	 * Return whether this transaction internally carries a savepoint,
	 * that is, has been created as nested transaction based on a savepoint.
	 * <p>This method is mainly here for diagnostic purposes, alongside
	 * {@link #isNewTransaction()}. For programmatic handling of custom
	 * savepoints, use the operations provided by {@link SavepointManager}.
	 * @see #isNewTransaction()
	 * @see #createSavepoint()
	 * @see #rollbackToSavepoint(Object)
	 * @see #releaseSavepoint(Object)
	 */
	boolean hasSavepoint();

	/**
	 * Flush the underlying session to the datastore, if applicable:
	 * for example, all affected Hibernate/JPA sessions.
	 * <p>This is effectively just a hint and may be a no-op if the underlying
	 * transaction manager does not have a flush concept. A flush signal may
	 * get applied to the primary resource or to transaction synchronizations,
	 * depending on the underlying resource.
	 */
	@Override
	void flush();

    
    boolean isNewTransaction();

	/**
	 * Set the transaction rollback-only. This instructs the transaction manager
	 * that the only possible outcome of the transaction may be a rollback, as
	 * alternative to throwing an exception which would in turn trigger a rollback.
	 */
	void setRollbackOnly();

	/**
	 * Return whether the transaction has been marked as rollback-only
	 * (either by the application or by the transaction infrastructure).
	 */
	boolean isRollbackOnly();

	/**
	 * Return whether this transaction is completed, that is,
	 * whether it has already been committed or rolled back.
	 */
	boolean isCompleted();
}

3. Spring 事务-编程式事务

问题: 代码耦合度较高

package com.example.sqldemo.spring_transaction;


import com.example.sqldemo.mapper.SqlMapper;
import com.example.sqldemo.pojo.AuditModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;

@Component
public class SpringTransactionTest {

    @Resource
    private SqlMapper sqlMapper;

    /**
     * jdbc 的 数据库的一个连接的template ,用于执行各种的sql语句
     */
    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 事务管理器
     */
    @Autowired
    private PlatformTransactionManager transactionManager;

    /**
     * Spring的一个封装过的事物template: 可以设置事务的隔离级别和事务的传播行为
     */
    @Autowired
    private TransactionTemplate transactionTemplate;

    // 需要自己进行事物的提交和回滚
    public  void test1(String[] args) {
        // 1. 定义默认的事物属性
        DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
        // 2. 获取事务
        TransactionStatus status = transactionManager.getTransaction(definition);
        try {
            // 3. 执行sql
            jdbcTemplate.update("update user set money = ? where username = ?",100,"李四");
            // 提交事务
            transactionManager.commit(status);
        } catch (DataAccessException | TransactionException e) {
            e.printStackTrace();
            // 事务回滚
            transactionManager.rollback(status);
        }
    }

    // 使用 Spring封装的事物的template, 帮助你进行事物的提交和回滚
    public  void test2() {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                // 执行sql
                AuditModel auditModel = new AuditModel();
                auditModel.setId(1232313232);
                auditModel.setCountry("西班牙");
                auditModel.setUser("哈哈哈哈");
                sqlMapper.insert(auditModel);
            }
        });
    }
}

我们点进去这个execute() 方法, 可以看到 这个Spring的这个TransactionTemplate 它其实帮你做了这个提交和回滚的部分, 不需要自己来做这部分的逻辑. 很方便.

在这里插入图片描述


http://www.kler.cn/a/398429.html

相关文章:

  • 01.02、判定是否互为字符重排
  • 丹摩征文活动|丹摩助力selenium实现大麦网抢票
  • 【Node.js】使用 Node.js 需要了解多少 JavaScript?
  • 微信小程序设置屏幕安全距离
  • Pandas进行周期与时间戳转换
  • 阮一峰科技爱好者周刊(第 325 期)推荐工具:一个基于 Next.js 的博客和 CMS 系统
  • yolov8目标检测如何设置背景/无标签图像参与训练
  • cooper+隐含数+2元cooper
  • 编辑器vim 命令的学习
  • 快速了解Zookeeper和etcd实现的分布式锁
  • 关于宝塔无法在php中安装fileinfo
  • 信也科技和云杉网络的AI可观测性实践分享
  • 如何将32位数据转化1bit valid,1bit modified,19bit tag, 3 bit index, 8bit数据
  • 海康视频监控云台位置切换与拍照图片下载
  • 应用系统开发(10) 钢轨缺陷的检测系统
  • 十九、Linux网络编程(三)
  • 智能网页内容截图工具:AI助力内容提取与可视化
  • 3D Gaussian Splatting的全面理解
  • vue2+3 —— Day5/6
  • 金融行业国产数据库容灾建设五大难点及解决方案
  • Web3D 与 AI 的结合重塑虚拟世界与智能应用
  • mysql 示例验证demo
  • 多目标优化算法:多目标红嘴蓝鹊优化算法(MORBMO)求解ZDT1、ZDT2、ZDT3、ZDT4、ZDT6,提供完整MATLAB代码
  • 卡尔曼滤波器
  • 调用门提权
  • 两个方法,取消excel数据隐藏