Spring-事务学习
spring事务
1. 什么是事务?
事务其实是一个并发控制单位,是用户定义的一个操作序列,这些操作要么全部完成,要不全部不完成,是一个不可分割的工作单位。事务有 ACID 四个特性,即:
- 原子性(Atomicity):事务中的所有操作,或者全部完成,或者全部不完成,是一个不可分割的工作单元。
- 一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。
- 隔离性(Isolation):多个事务之间是独立的,不相互影响的。
数据库允许多个并发事务同时对数据进行读写和修改, 隔离性可以防止多个事务并发执行时由于交叉执行而导致的数据的不一致。事物分为不同的隔离级别。
- 读未提交
- 读已提交
- 可重复读(数据库的默认的事物隔离级别)
- 串行化
- 持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
为了解释清楚这个问题,我们举个简单的例子:银行里树哥要给小黑转 1000 块钱,这时候会有两个必要的操作:
- 将树哥的账户余额减少 1000 元。
- 将小黑的账户余额增加 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 它其实帮你做了这个提交和回滚的部分, 不需要自己来做这部分的逻辑. 很方便.