一文搞懂Spring事务传播行为(Transaction Propagation)

【Spring】事务和事务的传播机制 将一组操作封装在一起执行,要么全部成功,要么全部失败。 阅读详情

事务的传播行为是为了解决业务层方法之间互相调用的事务问题,当一个事务方法被另一事务方法调用时,不同的传播行为会产生不同的结果。本文将结合代码实例,探讨一下如何正确使用事务的传播行为。

说明:本篇内容基于 MySQL(8.0.30-1.el8)及 SpringBoot(3.3.5)进行测试。

事务传播行为

Spring通过Propagation枚举类定义了7种传播行为。

代码案例

接下来我们通过代码案例充分了解一下这些传播行为的用法。

先定义两个内部服务PropagationAddUser1Service、PropagationAddUser2Service,用于实现数据库的插入。

@Service
public class PropagationAddUser1ServiceImpl implements PropagationAddUser1Service {

    @Resource
    private User1Mapper user1Mapper;
    
    // 不使用事务插入
    @Override
    public void add(User1 user) {
        user1Mapper.insert(user);
    }
    
    // 其他方法...
}
@Service
public class PropagationAddUser2ServiceImpl implements PropagationAddUser2Service {

    @Resource
    private User2Mapper user2Mapper;
    
    // 不使用事务插入
    @Override
    public void add(User2 user) {
        user2Mapper.insert(user);
    }
    
    // 不使用事务插入,抛出异常
    @Override
    public void addThrow(User2 user) {
        user2Mapper.insert(user);
        // 模拟异常
        throw new RuntimeException();
    }
    
    // 其他方法...
}

再定义一个外部服务PropagationAddExampleImpl,用于实现外部方法调用内部服务的方法。

@Service
public class PropagationAddExampleImpl implements PropagationAddExample {
    
    private final PropagationAddUser1Service user1Service;
    private final PropagationAddUser2Service user2Service;
    
    @Autowired
    public PropagationAddExampleImpl(PropagationAddUser1Service user1Service, PropagationAddUser2Service user2Service) {
        this.user1Service = user1Service;
        this.user2Service = user2Service;
    }
    
    // 外部方法出现异常
    @Override
    public void noEx_no_no() {
        user1Service.add(createUser1());
        user2Service.add(createUser2());
        // 模拟异常
        throw new RuntimeException();
    }

    // 内部方法出现异常
    @Override
    public void no_no_noEx() {
        user1Service.add(createUser1());
        user2Service.addThrow(createUser2());
    }
    
    // 其他方法...
}

最终通过调用外部服务来测试结果。

比如上述两个外部方法noEx_no_no和no_no_noEx调用后的结果都为成功,因为没有使用事务,所以不会触发回滚。对应的测试用例如下:

@Test
void noEx_no_no() {
    assertThrows(RuntimeException.class, propagationAddExample::noEx_no_no);
    assertEquals(1, getUser1Count());
    assertEquals(1, getUser2Count());
}

@Test
void no_no_noEx() {
    assertThrows(RuntimeException.class, propagationAddExample::no_no_noEx);
    assertEquals(1, getUser1Count());
    assertEquals(1, getUser2Count());
}

上述外部方法,如果添加了@Transactional注解,即开启默认事务,此时整个外部方法将视为一个事务,出现异常会触发事务回滚,比如下方内部方法1和内部方法2产生的数据都会回滚。

// 外部方法出现异常
@Transactional
@Override
public void requiredEx_no_no() {
    user1Service.add(createUser1());
    user2Service.add(createUser2());
    // 模拟异常
    throw new RuntimeException();
}

// 内部方法出现异常
@Transactional
@Override
public void required_no_noEx() {
    user1Service.add(createUser1());
    user2Service.addThrow(createUser2());
}

这也是我们开发中最常见的使用方式,而通过传播行为可以实现更为复杂的业务场景。

1. REQUIRED

如果当前没有事务,就新建一个事务;如果当前存在事务,就加入到这个事务中。

我们平时使用的@Transactional注解默认就是使用此传播行为。

@Service
public class PropagationAddUser1ServiceImpl implements PropagationAddUser1Service {

    // 使用事务插入
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void addRequired(User1 user) {
        user1Mapper.insert(user);
    }
    
    // 其他方法...
}
@Service
public class PropagationAddUser2ServiceImpl implements PropagationAddUser2Service {

    // 使用事务插入
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void addRequired(User2 user) {
        user2Mapper.insert(user);
    }
    
    // 使用事务插入,抛出异常
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void addRequiredThrow(User2 user) {
        user2Mapper.insert(user);
        // 模拟异常
        throw new RuntimeException();
    }
    
    // 其他方法...
}
1.1 场景1:外部方法没有开启事务
1.1.1 外部方法出现异常
@Override
public void noEx_required_required() {
    user1Service.addRequired(createUser1());
    user2Service.addRequired(createUser2());
    throw new RuntimeException();
}

1.1.2 内部方法出现异常

@Override
public void no_required_requiredEx() {
    user1Service.addRequired(createUser1());
    user2Service.addRequiredThrow(createUser2());
}

1.2 场景2:外部方法开启事务
1.2.1 外部方法出现异常

@Transactional
@Override
public void requiredEx_required_required() {
    user1Service.addRequired(createUser1());
    user2Service.addRequiredThrow(createUser2());
    throw new RuntimeException();
}

1.2.2 内部方法出现异常

@Transactional
@Override
public void required_required_requiredEx() {
    user1Service.addRequired(createUser1());
    user2Service.addRequiredThrow(createUser2());
}

1.2.3 捕获内部方法的异常 

@Transactional
@Override
public void required_required_requiredCatch() {
    user1Service.addRequired(createUser1());
    try {
        user2Service.addRequiredThrow(createUser2());
    } catch (Exception ignored) {}
}

Spring官方关于UnexpectedRollbackException的描述:

However, in the case where an inner transaction scope sets the rollback-only marker, the outer transaction has not decided on the rollback itself, so the rollback (silently triggered by the inner transaction scope) is unexpected. A corresponding UnexpectedRollbackException is thrown at that point. This is expected behavior so that the caller of a transaction can never be misled to assume that a commit was performed when it really was not. So, if an inner transaction (of which the outer caller is not aware) silently marks a transaction as rollback-only, the outer caller still calls commit. The outer caller needs to receive an UnexpectedRollbackException to indicate clearly that a rollback was performed instead.

简单翻译一下:

在内部事务范围设置了仅回滚标记的情况下,外部事务本身并没有决定回滚,所以回滚(由内部事务静默触发的)是意外的,此时会抛出UnexpectedRollbackException。因此,如果一个内部事务默默地将一个事务标记为仅回滚,外部调用者仍然会提交,此时外部调用者需要收到一个意外回滚的异常,以明确表示已执行回滚。

2. REQUIRES_NEW

如果当前没有事务,就新建一个事务;如果当前存在事务,就挂起当前事务并新建一个事务。

新建如下方法,@Transactional注解的propagation参数设置为Propagation.REQUIRES_NEW。(方法实现内容不变,此处省略,后续不再赘述)

// 使用事务插入
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void addRequiresNew(User1 user) {...}
// 使用事务插入
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void addRequiresNew(User2 user) {...}

// 使用事务插入,抛出异常
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void addRequiresNewThrow(User2 user) {...}
2.1 场景1:外部方法没有开启事务
2.1.1 外部方法出现异常
@Override
public void noEx_new_new() {
    user1Service.addRequiresNew(createUser1());
    user2Service.addRequiresNew(createUser2());
    throw new RuntimeException();
}

2.1.2 内部方法出现异常

@Override
public void no_new_newEx() {
    user1Service.addRequiresNew(createUser1());
    user2Service.addRequiresNewThrow(createUser2());
}

2.2 场景2:外部方法开启事务
2.2.1 外部方法出现异常
@Transactional
@Override
public void requiredEx_new_new() {
    user1Service.addRequiresNew(createUser1());
    user2Service.addRequiresNew(createUser2());
    throw new RuntimeException();
}

 

2.2.2 内部方法出现异常 

@Transactional
@Override
public void required_new_newEx() {
    user1Service.addRequiresNew(createUser1());
    user2Service.addRequiresNewThrow(createUser2());
}


2.2.3 捕获内部方法的异常

@Transactional
@Override
public void required_new_newCatch() {
    user1Service.addRequiresNew(createUser1());
    try {
        user2Service.addRequiresNewThrow(createUser2());
    } catch (Exception ignored) {}
}

2.3 注意事项

Spring官方针对REQUIRES_NEW的说明:

The resources attached to the outer transaction will remain bound there while the inner transaction acquires its own resources such as a new database connection. This may lead to exhaustion of the connection pool and potentially to a deadlock if several threads have an active outer transaction and wait to acquire a new connection for their inner transaction, with the pool not being able to hand out any such inner connection anymore. Do not use PROPAGATION_REQUIRES_NEW unless your connection pool is appropriately sized, exceeding the number of concurrent threads by at least 1.

点击查看原文

简单解释一下:

当内部事务获取自己的资源,如新的数据库连接时,外部事务的资源将保存绑定状态。也就是说,使用REQUIRES_NEW会导致一个请求占用多个数据库连接,可能会导致连接池资源耗尽,并且可能导致死锁。除非连接池大小至少超过并发线程数,否则不要使用REQUIRES_NEW。

3. NESTED

如果当前没有事务,就新建一个事务(类似于REQUIRED);如果当前存在事务,则作为当前事务的子事务执行。

新建如下方法,@Transactional注解的propagation参数设置为Propagation.NESTED。

// 使用事务插入
@Transactional(propagation = Propagation.NESTED)
@Override
public void addNested(User1 user) {...}

 

// 使用事务插入
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void addNested(User2 user) {...}

// 使用事务插入,抛出异常
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void addNestedThrow(User2 user) {...}
3.1 场景1:外部方法没有开启事务
3.1.1 外部方法出现异常
@Override
public void noEx_nested_nested() {
    user1Service.addNested(createUser1());
    user2Service.addNested(createUser2());
    throw new RuntimeException();
}

 

3.1.2 内部方法出现异常

@Override
public void no_nested_nestedEx() {
    user1Service.addNested(createUser1());
    user2Service.addNestedThrow(createUser2());
}

 

3.2 场景2:外部方法开启事务
3.2.1 外部方法出现异常
@Transactional
@Override
public void requiredEx_nested_nested() {
    user1Service.addNested(createUser1());
    user2Service.addNested(createUser2());
    throw new RuntimeException();
}

 3.2.2 内部方法出现异常

@Transactional
@Override
public void required_nested_nestedEx() {
    user1Service.addNested(createUser1());
    user2Service.addNestedThrow(createUser2());
}

3.2.3 捕获内部方法的异常

@Transactional
@Override
public void required_nested_nestedCatch() {
    user1Service.addNested(createUser1());
    try {
        user2Service.addNestedThrow(createUser2());
    } catch (Exception ignored) {}
}

 

3.3 注意事项

Spring官方针对NESTED的说明:

PROPAGATION_NESTED uses a single physical transaction with multiple savepoints that it can roll back to. Such partial rollbacks let an inner transaction scope trigger a rollback for its scope, with the outer transaction being able to continue the physical transaction despite some operations having been rolled back. This setting is typically mapped onto JDBC savepoints, so it works only with JDBC resource transactions. See Spring’s DataSourceTransactionManager.

点击查看原文

此内容中需要注意的是,NESTED仅适用于JDBC资源事务。

3.4 NESTED 与 REQUIRED 对比

传播行为NESTED与REQUIRED的测试结果有许多相似之处,但区别在于REQUIRED是同一事务,NESTED是嵌套事务。

换句话说,如果REQUIED的事务出现异常,同一事务内的所有数据都会回滚;而NESTED的父事务回滚会导致子事务回滚,子事务回滚不会导致父事务回滚(子事务的异常没有抛出给父事务就不会回滚)。

4 SUPPORTS

如果当前没有事务,就以非事务方式执行;如果当前存在事务,就加入到这个事务中。

新建如下方法,@Transactional注解的propagation参数设置为Propagation.SUPPORTS。

 

// 使用事务插入
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public void addSupports(User1 user) {...}
// 使用事务插入
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public void addSupports(User2 user) {...}

// 使用事务插入,抛出异常
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public void addSupportsThrow(User2 user) {...}
4.1 场景1:外部方法没有开启事务
4.1.1 外部方法出现异常
@Override
public void noEx_supports_supports() {
    user1Service.addSupports(createUser1());
    user2Service.addSupports(createUser2());
    throw new RuntimeException();
}

4.1.2 内部方法出现异常
@Override
public void no_supports_supportsEx() {
    user1Service.addSupports(createUser1());
    user2Service.addSupportsThrow(createUser2());
}

4.2 场景2:外部方法开启事务
4.2.1 外部方法出现异常
@Transactional
@Override
public void requiredEx_supports_supports() {
    user1Service.addSupports(createUser1());
    user2Service.addSupports(createUser2());
    throw new RuntimeException();
}

4.2.2 内部方法出现异常

@Transactional
@Override
public void required_supports_supportsEx() {
    user1Service.addSupports(createUser1());
    user2Service.addSupportsThrow(createUser2());
}

 

4.2.3 捕获内部方法的异常

@Transactional
@Override
public void required_supports_supportsCatch() {
    user1Service.addSupports(createUser1());
    try {
        user2Service.addSupportsThrow(createUser2());
    } catch (Exception ignored) {}
}

 

5 MANDATORY

如果当前没有事务,就抛出异常;如果当前存在事务,就加入到这个事务中。

新建如下方法,@Transactional注解的propagation参数设置为Propagation.MANDATORY。

// 使用事务插入
@Transactional(propagation = Propagation.MANDATORY)
@Override
public void addMandatory(User1 user) {...}

5.1 场景1:外部方法没有开启事务
服务结果分析
服务1异常外部方法没有事务,直接抛出异常,不会执行
服务2异常外部方法没有事务,直接抛出异常,不会执行

此时抛出的异常为:org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'。

5.2 场景2:外部方法开启事务
5.2.1 外部方法出现异常
@Transactional
@Override
public void requiredEx_mandatory_mandatory() {
    user1Service.addMandatory(createUser1());
    user2Service.addMandatory(createUser2());
    throw new RuntimeException();
}
服务结果分析
服务1回滚外部方法存在事务,服务1将使用该事务,以该事务的规则执行,REQUIRED的规则在此时会触发回滚
服务2回滚外部方法存在事务,服务2将使用该事务,以该事务的规则执行,REQUIRED的规则在此时会触发回滚
5.2.2 内部方法出现异常
@Transactional
@Override
public void required_mandatory_mandatoryEx() {
    user1Service.addMandatory(createUser1());
    user2Service.addMandatoryThrow(createUser2());
}
服务结果分析
服务1回滚外部方法存在事务,服务1将使用该事务,以该事务的规则执行,REQUIRED的规则在此时会触发回滚
服务2回滚外部方法存在事务,服务2将使用该事务,以该事务的规则执行,REQUIRED的规则在此时会触发回滚
5.2.3 捕获内部方法的异常

6 NOT_SUPPORTED

以非事务方式执行;如果当前存在事务,就挂起当前事务。

新建如下方法,@Transactional注解的propagation参数设置为Propagation.NOT_SUPPORTED。

// 使用事务插入
@Transactional(propagation = Propagation.NOT_SUPPORTED)
@Override
public void addNotSupported(User1 user) {...}
// 使用事务插入
@Transactional(propagation = Propagation.NOT_SUPPORTED)
@Override
public void addNotSupported(User2 user) {...}

// 使用事务插入,抛出异常
@Transactional(propagation = Propagation.NOT_SUPPORTED)
@Override
public void addNotSupportedThrow(User2 user) {...}
6.1 场景1:外部方法没有开启事务

此时直接以非事务方式执行,不再赘述。

6.2 场景2:外部方法开启事务
6.2.1 外部方法出现异常
@Transactional
@Override
public void requiredEx_not_not() {
    user1Service.addNotSupported(createUser1());
    user2Service.addNotSupported(createUser2());
    throw new RuntimeException();
}
服务结果分析
服务1成功外部方法存在事务,将挂起当前事务,服务1会以非事务方式执行,不会回滚
服务2成功外部方法存在事务,将挂起当前事务,服务2会以非事务方式执行,不会回滚
6.2.2 内部方法出现异常
@Transactional
@Override
public void required_not_notEx() {
    user1Service.addNotSupported(createUser1());
    user2Service.addNotSupportedThrow(createUser2());
}
服务结果分析
服务1成功外部方法存在事务,将挂起当前事务,服务1会以非事务方式执行,不会回滚
服务2成功外部方法存在事务,将挂起当前事务,服务1会以非事务方式执行,不会回滚
6.2.3 捕获内部方法的异常

7 NEVER

以非事务方式执行;如果当前存在事务,就抛出异常。

新建如下方法,@Transactional注解的propagation参数设置为Propagation.NEVER。

// 使用事务插入
@Transactional(propagation = Propagation.NEVER)
@Override
public void addNever(User1 user) {...}
// 使用事务插入
@Transactional(propagation = Propagation.NEVER)
@Override
public void addNever(User2 user) {...}

// 使用事务插入,抛出异常
@Transactional(propagation = Propagation.NEVER)
@Override
public void addNeverThrow(User2 user) {...}

 

7.1 场景1:外部方法没有开启事务
7.1.1 外部方法出现异常
@Override
public void noEx_never_never() {
    user1Service.addNever(createUser1());
    user2Service.addNever(createUser2());
    throw new RuntimeException();
}
服务结果分析
服务1成功外部方法没有事务,以非事务形式执行,不会回滚
服务2成功外部方法没有事务,以非事务形式执行,不会回滚
7.1.2 内部方法出现异常
@Override
public void no_never_neverEx() {
    user1Service.addNever(createUser1());
    user2Service.addNeverThrow(createUser2());
}
服务结果分析
服务1成功外部方法没有事务,以非事务形式执行,不会回滚
服务2成功外部方法没有事务,以非事务形式执行,不会回滚
7.2 场景2:外部方法开启事务
@Transactional
@Override
public void requiredEx_never_never() {
    user1Service.addNever(createUser1());
    user2Service.addNever(createUser2());
}
服务结果分析
服务1异常外部存在事务,直接抛出异常,不会执行
服务2异常外部存在事务,直接抛出异常,不会执行

此时抛出的异常为:org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'。

 

Spring事务回滚机制解析:UnexpectedRollbackException的根源与解决方案 事务管理是数据库操作的核心机制,它通过ACID特性确保数据一致性。Spring框架通过声明式事务管理简化了事务控制,但其底层基于AOP代理和回滚标记机制实现。当嵌套事务中内层操作触发回滚标记,而外层试图提交时,就会产生UnexpectedRollbackException异常,这体现了事务传播机制与异常处理的微妙冲突。理解事务传播行为(如PROPAGATION_REQUIRED)和回滚标记的不可逆特性,对于设计健壮的数据访问层至关重要。在实际工程中,合理划分事务边界、精确配置rollbackFor属性,能有 阅读详情

相关推荐

Spring事务UnexpectedRollbackException:原理、场景与解决方案深度解析

在Java企业级应用开发中,事务管理是保障数据一致性的核心技术。Spring框架通过声明式事务管理,基于AOP和事务传播机制,为开发者提供了便捷的事务控制能力。其核心原理在于维护事务状态,并通过rollback-only标记来确保异常场景下的数据安全。这一机制在多层服务调用、嵌套事务等复杂场景中具有重要技术价值,能有效防止脏提交。然而,若事务边界与异常处理边界不一致,例如内层事务异常被外层捕获但未重新抛出,就会触发UnexpectedRollbackException,导致事务意外回滚。本文聚焦于这一典型问

weixin_30571465的博客 345

事务的7种传播行为

另一方面, PROPAGATION_NESTED 开始一个 “嵌套的” 事务, 它是已经存在事务的一个真正的子事务. 潜套事务开始执行时, 它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交。两个事务不是一个真正的嵌套事务。举例说明:有两个事务方法,一个是方法A,一个是方法B,方法A中调用了方法B,那方法B是开启一个事务运行还是在方法A中的事务中运行,是由方法B的事务传播行为控制的。

glenshappy的专栏 5073

Transactional注解在多线程为啥不生效?3个真实案例带你彻底搞懂事务传播机制

本文深入解析了@Transactional注解在多线程环境下失效的原因,通过三个真实案例详细探讨了事务传播机制的核心原理及解决方案。文章重点分析了异步任务中的异常吞噬、线程池复用导致的事务混淆以及异常类型不匹配等典型问题,并提供了编程式事务与声明式事务的对比实践,帮助开发者彻底搞懂多线程事务处理。

weixin_29251131的博客 105

Spring的事务传播机制(通俗易懂)

概述 Spring的传播机制有7种,在枚举Propagation中有定义。 1.REQUIRED PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的默认设置。 @Transactional(propagation= Propagation.REQUIRED) public void methodA(){ methodB(); // do something } @Transactional(propagation= P

Samdom的博客 1万+

Spring JDBC实战:从连接管理到批量操作的生产级指南

JDBC是Java数据库交互的底层基石,其核心在于Connection生命周期管理、SQL执行控制与异常语义转换。Spring JDBC通过JdbcTemplate将JDBC标准化封装,在保持SQL完全可控的前提下,解决资源泄漏、堆栈不透明、事务边界模糊等高频问题。相比MyBatis或JPA,它不生成SQL、不隐藏连接、不代理执行,而是提供轻量、可调试、多数据源友好的执行契约。在微服务多数据源、OceanBase负载均衡、Spring AI 2.0集成等复杂场景下,JdbcTemplate因其确定性成为事务

weixin_33690367的博客 352

Spring AOP实战:横切关注点解耦与切面开发避坑指南

面向Java Web开发者,Spring AOP是一种面向切面的编程范式,用于将日志、事务、监控等横切关注点从业务逻辑中分离。其核心基于代理机制与织入原理,通过Pointcut精准匹配连接点,Advice定义增强行为,Aspect封装可复用逻辑。相比HandlerInterceptor(仅限Web层)和手动代理(无法处理自调用),Spring AOP依托Spring容器统一管理代理Bean,保障跨层调用与依赖注入场景下的稳定拦截。技术价值在于提升代码内聚性、降低维护成本、支持非侵入式功能扩展。典型应用场景包

weixin_30240349的博客 431

Spring Transaction属性之Propagation

我们平常使用spring transaction时,我们大多都习惯于使用@Transactional,对于这个annotation可以有些什么配置,在什么情况下使用了解比较少。这篇博客主要关注于@Transactional中4个属性之一 -- propagation。 Propagation取值: REQUIRED(默认值):在有transaction状态下执行;如当前没有transa

kiwi_coder 7万+

spring事务Propagation及其实现原理(传播属性示例分析)

spring事务传播属性示例分析 在TransactionDefinition类中,spring提供了6种传播属性,接下来分别用简单示例来说明。 温馨提醒:下文提到的加入当前事务,指的是底层使用同一个Connection,但是事务状态对象是可以重新创建的,并不影响。文章提到的当前只存在一个事务,表示的是共用底层的一个Connection,而不在乎创建了多少个事务状态对象(TransactionS...

十年呵护的专栏 3823

一文搞懂Spring中的事务管理

什么是事务? 有一个最典型的例子用来描述事务: 在银行里,一个人A给另一个人B转账100元,那么银行会有以下两个操作: 给A的账户扣100元 给B的账户增加100元 但如果在转账的过程中银行系统出了问题,可能会有以下情况: A的账户扣了钱,B的账户没有增加钱 A的账户没扣钱,B的账户增加了钱 上述两种情况都是不符合期望的,但故障总是可能会发生的,那怎么解决这个问题呢?就是用事务。事务是一系...

程铭程铭你快成名的博客 5190

统信UOS安装CH384串口卡驱动

本文讲解如何在统信UOS系统下安装CH384 PCIE多串口驱动安装过程,CPU为飞腾D2000。其他Linux内核系统安装亦可参照类似方法。

shjhuang的专栏 1887

28、解码清华SSVEP基准数据集:从EEG信号到深度学习模型的实战指南

本文详细解析了清华大学SSVEP基准数据集的处理与深度学习模型构建全流程。从EEG信号预处理、数据维度变换到SSVEP分类模型设计,提供了实战代码示例和关键技巧,帮助读者掌握脑机接口领域的数据处理方法与模型优化策略。

weixin_29029995的博客 176

搞懂Spring事务机制,一篇文章就够了

文章目录前言1 事务1.1 概念1.2 特性1.3 隔离级别1.4 传播特性1.5 配置方式1.5.1 编程式事务1.5.2 声明式事务2 实战2.1 PROPAGATION_NEVER 机制2.2 PROPAGATION_NOT_SUPPORTED 机制2.3 PROPAGATION_SUPPORTS 机制2.4 PROPAGATION_REQUIRES_NEW 机制2.5 PROPAGATION_NESTED 机制2.6 PROPAGATION_REQUIRED 机制2.7 PROPAGATION_MA

沸羊羊_ 4388

普冉PY32F002B ADC内部参考电压VREFINT的误差补偿与低功耗优化实践

本文详细介绍了普冉PY32F002B单片机在锂电池供电场景下ADC内部参考电压VREFINT的误差补偿与低功耗优化实践。通过分析GPIO配置、分压电阻匹配、采样时间设置等硬件设计要点,结合实时测量VREFINT电压值和软件补偿算法,有效提升了ADC测量精度至5mV以内,并实现了分压电路功耗控制与采样频率优化,为低成本消费电子项目提供了完整的解决方案。

847

一文搞懂spring事务

spring事务的创建流程是怎样的?spring事务有哪些传播类型?spring事务为什么不生效?一文看懂spring事务

Darlight的博客 310

利用ArcGIS的模型构建器实现批量投影栅格和批量克里金插值

博主要批量投影几百个栅格,但是ArcGIS中的投影栅格的批处理工具需要手动一条条设置参数,还是麻烦,因此学习了使用模型构建器(ModelBuilder)来批量投影栅格,可以导入需投影栅格的文件夹,然后迭代投影,并按栅格原名逐个输出到指定目录。 1.在工具箱里构建模型 在arctool box里右键点击空白处,选择【添加工具箱】,点击ArcGIS默认工作目录的工具箱进行添加,然后Toolbox就会被添加到ArcToolbox页面,右键点击Toolbox,选择“新建”-“模型” 2.编写模型 (1).

qq_36958801的博客 1万+

10.2 在新能源、储能及电网节点的应用实践

构网型变流器技术在电力系统中的应用进展 构网型变流器技术正从理论研究走向规模化工程应用,为新能源并网提供主动支撑能力。该技术在光伏电站采用"部分构网"混合架构,由构网单元实现黑启动和弱网稳定;在风电场利用叶轮动能提供惯量响应。储能系统是理想的构网载体,可提供快速调频和动态电压支撑。在电网节点,构网型STATCOM可增强弱电网电压稳定性,大容量变流器可替代传统调相机。当前面临标准滞后、宽频振荡风险等共性挑战,需在可靠性、经济性间取得平衡。系统级协调控制和精确阻抗建模是应用成功的关键。

技术工作者 1112

搞懂Spring的事务传播机制

搞懂Spring的事务传播机制 事务传播枚举: org.springframework.transaction.annotation.Propagation REQUIRED(0), SUPPORTS(1), MANDATORY(2), REQUIRES_NEW(3), NOT_SUPPORTED(4), NEVER(5), NESTED(6); @Transactional(propagation= Propagation.REQUIRED) 结论:   使用当前的事务,如果当前没有事务,则自己新建一个

码瘾的空间 364

数学之美 | 图论和网络爬虫

文章目录概述图论网络爬虫分析BFSDFSBFS + DFS参考资料 概述 这篇文章主要给大家介绍一下计算机算法中非常重要的一部分——图论,以及它在生活中的应用——网络爬虫。   图论 离散数学是当代数学的一个重要的分支,也是计算机科学的数学基础。它又包括四个分支,而图论便是其中一支,另外三个分别是:数理逻辑、集合论、近代数学。 图论中的图由一些节点和边构成,比如下面这张图 。 在图论中一个很基础...

小小酥梨的博客 3231

一文搞懂 Spring 数据库事务操作!

作者|阿文,责编 | 郭芮头图 | 优快云 下载自东方IC出品 | 优快云(ID:优快云news)今天我们一起了解下Spring的数据库事务操作。在操作数据库时,我们经常会使...

优快云资讯 4133

MISRA C 详解 · 专栏06:2023 与 2025 更新总览(相对 2012 的差异)

本专栏 01~05 篇基于(143 规则 + 16 指令)。这六年间标准又前进了两步——(大改)和(微调)。本文补充说明「相对 2012,标准变在哪」,并给出新增规范的代表性示例。

XavierKong的博客 74

从 SAP GUI 到 API 自动化,为什么 SAP 团队必须把 API 拉到路线图中央

摘要: SAP项目正从传统手工操作转向API驱动,以应对业务敏捷性需求。API不仅是技术接口,更是核心业务能力的标准化封装,助力自动化、低代码、AI集成和系统升级。通过SAP Business Accelerator Hub等工具,企业可复用标准API替代定制开发,减少技术债。API还赋能自动化平台、实时集成和AI Agent执行,确保安全治理与审计追踪。未来,API将成为企业系统与AI交互的核心桥梁,缺乏API将迫使业务依赖脆弱的UI自动化方案。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 304

《Java 100 天进阶之路》第76篇:Spring事务(2026版)

@Transactional是Java后端每天都要用的注解。一文掌握ACID四大特性、编程式vs声明式事务、@Transactional底层AOP原理、5种隔离级别(解决脏读/不可重复读/幻读)、7种传播行为(REQUIRED/REQUIRES_NEW/NESTED等)、12+种失效场景(自调用/非public/异常被吞等)。附完整代码示例、避坑清单、面试高频考点与追问陷阱。搞懂Spring事务,就搞懂了数据一致性的最后一道防线!

折哥|智能物流与Java实战,副高数据库工程师。深耕出版社物流WMS/OMS(线体/立库/VGA),也分享Java进阶与OMS电商对接。Oracle→PG实战派。相信沉淀可迁移能力,分享通用技术,不藏不虚。 6678

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

spring

在应用开发中用的非常多, @Component注解是一个通用注解,可以用在于任何类上。包括普通java类,业务逻辑组件,持久化对象等等。通过@Component注解spring自动创建该类的实例注入SpringIOC容器中。@Bean是用于配置类中声明一个Bean的,它通常是用于配置类的方法上面,表示把这个方法的返回对象注册到Spring IOC容器中。通过@Bean自定义Bean的创建和初始化过程,包括指定Bean的名称、作用域、依赖关系等。1.用途不同@Component用于标识普通的类。

黑冰[̲̅V̲̅I̲̅P̅] 818

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Spring AOP核心原理与实践:从代理机制到高级应用场景

面向切面编程(AOP)是一种重要的编程范式,它通过将横切关注点(如日志、事务、安全等)从核心业务逻辑中分离出来,实现代码的模块化和解耦。其核心原理基于代理模式,在程序运行时动态地将额外逻辑织入到目标方法中,从而在不修改原有代码的情况下增强功能。这一技术为软件工程带来了显著价值,包括提升代码复用性、降低耦合度、增强可维护性。在实际应用中,AOP广泛用于日志记录、事务管理、权限控制、性能监控等通用场景。本文以Spring AOP为例,深入剖析其核心概念与实现机制,特别是JDK动态代理与CGLIB代理的差异与选择

weixin_30784501的博客 311

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

AI时代Java工程师进阶指南:聚焦并发、JVM与系统设计构建核心竞争力

在软件开发领域,并发编程是处理多任务同时执行的核心技术,它通过线程管理、锁机制和同步工具来确保数据一致性与系统性能。其原理基于操作系统调度与Java内存模型,旨在提升资源利用率和响应速度。这项技术的价值在于支撑高并发、低延迟的互联网服务,是构建电商、金融交易等大规模系统的基石。随着AI辅助编程工具的普及,基础代码生成效率大幅提升,工程师更需深入理解底层机制。本文聚焦Java生态,探讨在AI赋能下,如何将精力集中于并发编程、JVM调优、MySQL深度优化等AI难以替代的硬核领域,通过掌握JUC工具包、GC算法

weixin_30883311的博客 426

Spring事务的 7 种传播行为

Spring 框架中的事务传播行为定义了在多个事务操作嵌套执行时,如何处理事务的传播和管理。Spring 提供了多种事务传播行为,以满足不同的业务需求。

qq_45110186的博客 7404
上一篇: Spring @Transactional 你真的会用吗???
下一篇: 用Java Executors创建线程池的9种方法
加班不秃顶
博客等级 码龄7年 1822粉丝 599原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值