Spring 事务:是spring 通过 aop实现的一套事务管理功能,可以定义隔离级别,传播行为,回滚规则,事务超时,是否只读。
1、隔离级别 对应mysql 几乎都是定义为 可重复读
2、传播特性则不同,不同的业务场景,使用的特性非常不同
spring 事务的创建的时间点:通过aop 在调用需要开启事务的方法前开启,方法结束后提交事务(准确的说还要看事务的传播行为),或者抛出异常回滚事务
事务传播行为(Transaction Propagation Behavior):定义当前方法的事务和调用方事务的关系,比如:可以加入到调用方的事务,也可以重新开启事务,亦或开始事务保存点等。
Spring 提供的几种事务传播行为:
1.PROPAGATION_REQUIRED(加入已有事务)
尝试加入已经存在的事务中,如果没有则开启一个新的事务。
注意:如果这个事务回滚,因为和调用方使用的是一个事务,所以调用方的事务同时回滚,这一点也是和nested事务的区别之处 (这里都是说内层的事务传播特性,调用方已经开启了事务)
2.RROPAGATION_REQUIRES_NEW(独立事务)
挂起当前存在的事务,并开启一个全新的事务,新事务与已存在的事务之间彼此没有关系。
注意:如果做到没有任何关系 ?重新启动一个connection连接,和当前连接没有关系,自然事务也完全隔离了
3.PROPAGATION_NESTED(嵌套事务)
在当前事务上开启一个子事务(Savepoint),如果递交主事务。那么连同子事务一同递交。如果递交子事务则保存点之前的所有事务都会被递交。
注意:嵌套事务本身不会开启新的事务,即用的是已经存在的事务,nested事务抛出异常,调用方捕获异常,则调用方的事务不会回滚(savepoint特性);当然如果继续抛出或者调用方没有捕获异常亦或调用方有异常,都回滚(这里都是说内层的事务传播特性,调用方已经开启了事务)
更专业的描述为:嵌套事务:就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。
4.PROPAGATION_SUPPORTS(跟随环境)
是指 Spring 容器中如果当前没有事务存在,就以非事务方式执行;如果有,就使用当前事务。
5.PROPAGATION_NOT_SUPPORTED(非事务方式)
是指如果存在事务则将这个事务挂起,并使用新的数据库连接。新的数据库连接不使用事务。
6.PROPAGATION_NEVER(排除事务)
当存在事务时抛出异常,否则就已非事务方式运行。
7.PROPAGATION_MANDATORY(需要事务)
如果不存在事务就抛出异常,否则就已事务方式运行。
其中第4-7的事务行为比较简单,不再详述;最应该引起重视的是:RROPAGATION_REQUIRES_NEW ,当前方法启动的事务和调用方的事务没有关系,他和调用方的数据库连接都不是一个。
如果有时间,最好运行下下面的用例,仔细体会下不同事务的传播属性的实际情况:
测试用例:
/** * @author xinchun.wang */ @Service public class UserDaoImpl { @Resource private JdbcTemplate jdbcTemplate; public void testWithOutTransaction() { String info = "testWithOutTransaction_"+System.currentTimeMillis() + UUID.randomUUID().toString(); jdbcTemplate.execute("INSERT INTO user_log(info, `time`) VALUES ( '"+info+"','"+info+"')"); } /** * 挂起当前存在的事务,并开启一个全新的事务,新事务与已存在的事务之间彼此没有关系。 */ @Transactional(value = "transactionManager",propagation=Propagation.REQUIRES_NEW) public void testTransactionNew() { String info = "Afater_insertLoginLog_"+System.currentTimeMillis() + UUID.randomUUID().toString(); jdbcTemplate.execute("INSERT INTO user_log(info, `time`) VALUES ( '"+info+"','"+info+"')"); Connection connection = ((ConnectionHolder)(TransactionSynchronizationManager.getResourceMap().values().iterator().next())).getConnection(); System.out.println("$$$$$$$"+connection.hashCode()); } /** * 尝试加入已经存在的事务中,如果没有则开启一个新的事务。 */ @Transactional(value = "transactionManager",propagation=Propagation.REQUIRED) public void testTransactionRequired() { String info = "Before_tesTransactionRequired_"+System.currentTimeMillis() + UUID.randomUUID().toString(); jdbcTemplate.execute("INSERT INTO user_log(info, `time`) VALUES ( '"+info+"','"+info+"')"); if(true){ throw new RuntimeException("Error"); } info = "After_tesTransactionRequired_"+System.currentTimeMillis() + UUID.randomUUID().toString(); jdbcTemplate.execute("INSERT INTO user_log(info, `time`) VALUES ( '"+info+"','"+info+"')"); } /** * 在当前事务上开启一个子事务(Savepoint),如果递交主事务。那么连同子事务一同递交。如果递交子事务则保存点之前的所有事务都会被递交。 */ @Transactional(value = "transactionManager",propagation=Propagation.NESTED) public void testNestTransactionWithException() { String info = "testNestTransactionWithException_"+System.currentTimeMillis() + UUID.randomUUID().toString(); jdbcTemplate.execute("INSERT INTO user_log(info, `time`) VALUES ( '"+info+"','"+info+"')"); if(true){ throw new RuntimeException("Error"); } } /** * 在当前事务上开启一个子事务(Savepoint),如果递交主事务。那么连同子事务一同递交。如果递交子事务则保存点之前的所有事务都会被递交。 */ @Transactional(value = "transactionManager",propagation=Propagation.NESTED) public void testNestTransaction() { String info = "testNestTransaction_"+System.currentTimeMillis() + UUID.randomUUID().toString(); jdbcTemplate.execute("INSERT INTO user_log(info, `time`) VALUES ( '"+info+"','"+info+"')"); UserServiceImpl.printData("&&&&&&&&&&"); } }
/**
* @author xinchun.wang
*/
@Service
public class UserServiceImpl implements IUserService {
@Resource
private UserDaoImpl userDaoImpl;
/**
* 挂起当前存在的事务,并开启一个全新的事务,新事务与已存在的事务之间彼此没有关系。
*/
@Override
@Transactional(value = "transactionManager",propagation=Propagation.REQUIRED)
public void testTransactionNew() {
userDaoImpl.testWithOutTransaction();
Connection connection = ((ConnectionHolder)(TransactionSynchronizationManager.getResourceMap().values().iterator().next())).getConnection();
System.out.println("#######"+connection.hashCode());
userDaoImpl.testTransactionNew();
userDaoImpl.testTransactionRequired();
}
/**
* 嵌套事务失败,外部事务捕获异常,可以正常提交
* start transaction
* insert data1
* save savepoint1
* insert data2
* roback savepoint1
* commit
*/
@Override
@Transactional(value = "transactionManager",propagation=Propagation.REQUIRED)
public void testNestTransactionWithException() {
userDaoImpl.testWithOutTransaction();
try{
userDaoImpl.testNestTransactionWithException();
}catch(Exception e){
e.printStackTrace();
}
}
/**
*
* 调用者出现unchecked异常,却能触发所调用的nested事务的回滚.(外部事务失败,都取消)
* start transaction
* insert data1
* save savepoint1
* insert data2
* rollback
*/
@Override
@Transactional(value = "transactionManager",propagation=Propagation.REQUIRED)
public void testNestTransaction() {
UserServiceImpl.printData("########");
userDaoImpl.testWithOutTransaction();
userDaoImpl.testNestTransaction();
if(true){
throw new RuntimeException("Error");
}
}
@Override
@Transactional(value = "transactionManager",propagation=Propagation.REQUIRED)
public void testTransactionRequared() {
System.out.println(TransactionSynchronizationManager.getResourceMap().values());
Connection connection = ((ConnectionHolder)(TransactionSynchronizationManager.getResourceMap().values().iterator().next())).getConnection();
System.out.println("$$$$$$$"+connection.hashCode());
userDaoImpl.testWithOutTransaction();
try{
userDaoImpl.testTransactionRequired();
}catch(Exception e){
}
}
/** 通过这个,可以确定当前连接的hashcode*/
public static void printData(String key){
System.out.println(TransactionSynchronizationManager.getResourceMap().values());
Connection connection = ((ConnectionHolder)(TransactionSynchronizationManager.getResourceMap().values().iterator().next())).getConnection();
System.out.println(key+connection.hashCode());
}
}
最后:在事务修饰的方法内部,直接调用事务修饰的方法,如果没有通过aop代理来调用,不会有事务,也不会是一个数据库连接。
相关推荐
本项目"spring-transaction-demo"是一个用于演示Spring框架事务管理特性的实例。下面我们将详细探讨Spring事务的传播机制以及其在实际应用中的七种使用方式。 1. **Spring事务的概述** Spring事务管理是通过编程或...
这个jar包是Spring的事务管理模块,提供了声明式事务管理(Declarative Transaction Management)和编程式事务管理(Programmatic Transaction Management)。声明式事务管理是Spring的一大特色,通过在XML配置或...
<tx:advice id="txAdvice" transaction-manager="transactionManager"> *" propagation="REQUIRED"/> ``` 以上配置表明,所有在com.example.service包及其子包下的方法都将被包含在默认的REQUIRED事务传播...
Spring提供了一些内置的实现,如`JtaTransactionManager`,它可以配合JOTM(Java Open Transaction Manager)这样的JTA事务管理器进行分布式事务控制。在配置JOTM时,我们需要添加相应的依赖并配置相关参数。 最后...
- **事务传播行为**:当一个事务方法被另一个事务方法调用时,Spring提供了七种不同的传播行为,如PROPAGATION_REQUIRED(默认,新事务如果存在则加入,不存在则新建)、PROPAGATION_REQUIRES_NEW(总是新建事务,...
Spring Data JPA支持不同的事务传播属性,如PROPAGATION_REQUIRED(默认,新建或加入现有事务)、PROPAGATION_REQUIRES_NEW(新建事务,如果已有事务则挂起)等。测试需要覆盖这些场景,确保事务传播行为正确。 9....
`springboot-transaction-demo`项目是一个典型的示例,用于展示如何在Spring Boot中配置和使用事务管理。本项目着重于Spring的事务处理机制,这包括事务的声明式管理、编程式管理以及相关的异常处理策略。 1. **...
### Spring中的Transaction事务传播行为种类详解 #### 一、引言 在开发基于Spring框架的应用程序时,事务管理是确保数据一致性的重要手段之一。Spring框架提供了丰富的事务管理功能,其中包括了事务传播行为...
Spring JPA事务管理还支持多种事务传播行为,如PROPAGATION_REQUIRED(默认,新事务或加入当前事务)、PROPAGATION_REQUIRES_NEW(新事务,与当前事务隔离)等,可以根据业务需求选择合适的传播行为。 另外,我们还...
- **事务传播行为(Transaction Propagation)**: 在Spring中,当一个事务方法调用另一个事务方法时,需要明确指定事务如何传播。例如: - `REQUIRED`: 默认行为,如果当前存在事务,则加入;否则,新建一个事务。 ...
在本教程中,我们将深入探讨Spring框架中的事务管理,特别是基于XML配置的事务管理。Spring作为Java企业级应用开发的主流框架,其事务管理机制是核心功能之一,它确保了数据的一致性和完整性。在“spring-06.rar”...
本篇主要聚焦于"Spring 常用 Transaction Annotation",即声明式事务管理,这是一种更简洁、易于维护的事务控制方式。 首先,Spring的声明式事务管理基于AOP(面向切面编程),它允许我们在不修改业务代码的情况下...
3. New Features and Enhancements in Spring Framework 4.0 ............................................ 17 3.1. Improved Getting Started Experience .........................................................
Spring事务管理(Transaction Management)提供了一种声明式和编程式的事务处理方式,使得开发者能够在不关注底层事务实现细节的情况下,轻松地进行事务控制。本文将通过对"spring-trasaction"项目的源码分析,深度...
Spring提供了多种事务管理器实现,如`DataSourceTransactionManager`用于JDBC事务,`HibernateTransactionManager`用于Hibernate事务,以及`JtaTransactionManager`用于Java Transaction API (JTA)事务。...
3. New Features and Enhancements in Spring Framework 4.0 ............................................ 17 3.1. Improved Getting Started Experience .........................................................
<tx:advice id="transactionAdvice" transaction-manager="transactionManager"> *" propagation="REQUIRED"/> (* com.example.service.*.*(..))"/> <aop:advisor advice-ref="transactionAdvice" pointcut...
<tx:advice id="txAdvice" transaction-manager="transactionManager"> *" propagation="REQUIRED"/> ``` 以上就是Spring与MyBatis整合的基本步骤和关键知识点。这个过程使得开发者能够利用Spring的强大功能...
在Spring框架中,事务管理(Transaction Management)是一个关键特性,它确保了数据的一致性和完整性。本篇将深入探讨"spring_tx"案例源码中的事务管理相关知识点。 1. **Spring事务管理模型** Spring提供了两种...
除了基本的事务控制,Spring还提供了丰富的事务属性,如传播行为(PROPAGATION_REQUIRED、PROPAGATION_SUPPORTS等)、隔离级别(ISOLATION_DEFAULT、ISOLATION_READ_UNCOMMITTED等)和事务超时设置,允许开发者根据...