Spring中怎么使用注解声明事务

发布时间:2021-07-30 16:21:38 作者:Leah
来源:亿速云 阅读:189
# Spring中怎么使用注解声明事务

## 1. 事务管理概述

在Spring框架中,事务管理是核心功能之一。Spring提供了两种事务管理方式:
- **编程式事务**:通过编写代码手动管理事务
- **声明式事务**:通过配置(XML或注解)声明事务行为

其中**基于注解的声明式事务**因其简洁性和易用性成为最常用的方式。

## 2. 基础环境配置

### 2.1 添加依赖
```xml
<!-- Spring事务核心依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.3.18</version>
</dependency>

<!-- 数据库相关 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.18</version>
</dependency>
<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>4.0.3</version>
</dependency>

2.2 配置数据源和事务管理器

@Configuration
@EnableTransactionManagement  // 启用注解驱动的事务管理
public class AppConfig {
    
    @Bean
    public DataSource dataSource() {
        HikariDataSource ds = new HikariDataSource();
        ds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        ds.setUsername("root");
        ds.setPassword("password");
        return ds;
    }
    
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }
}

3. @Transactional注解详解

3.1 基本使用

在方法或类上添加@Transactional注解即可声明事务:

@Service
public class UserServiceImpl implements UserService {
    
    @Autowired
    private UserDao userDao;
    
    @Transactional
    @Override
    public void createUser(User user) {
        userDao.insert(user);
    }
}

3.2 注解属性配置

属性名 说明 默认值
propagation 事务传播行为 REQUIRED
isolation 事务隔离级别 DEFAULT
timeout 事务超时时间(秒) -1(不超时)
readOnly 是否只读事务 false
rollbackFor 触发回滚的异常类型 {}
noRollbackFor 不触发回滚的异常类型 {}

示例:

@Transactional(
    propagation = Propagation.REQUIRED,
    isolation = Isolation.READ_COMMITTED,
    timeout = 30,
    rollbackFor = {SQLException.class},
    noRollbackFor = {NullPointerException.class}
)
public void transferMoney(Long from, Long to, BigDecimal amount) {
    // 业务逻辑
}

4. 事务传播行为

Spring定义了7种传播行为:

传播行为类型 说明
REQUIRED 如果当前存在事务,则加入该事务;否则新建事务
SUPPORTS 如果当前存在事务,则加入该事务;否则以非事务方式运行
MANDATORY 必须在一个已有的事务中执行,否则抛出异常
REQUIRES_NEW 新建事务,如果当前存在事务则挂起
NOT_SUPPORTED 以非事务方式执行,如果当前存在事务则挂起
NEVER 以非事务方式执行,如果当前存在事务则抛出异常
NESTED 如果当前存在事务,则在嵌套事务内执行

示例:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logOperation(OperationLog log) {
    // 记录操作日志,需要独立事务
}

5. 事务隔离级别

Spring支持的标准隔离级别:

隔离级别 说明
DEFAULT 使用底层数据库默认隔离级别
READ_UNCOMMITTED 读未提交
READ_COMMITTED 读已提交
REPEATABLE_READ 可重复读
SERIALIZABLE 串行化

示例:

@Transactional(isolation = Isolation.READ_COMMITTED)
public User getUserWithBalance(Long userId) {
    // 需要读取已提交的数据
}

6. 最佳实践

  1. 注解位置

    • 通常建议在Service层添加事务注解
    • 在类级别添加注解表示该类所有public方法都应用事务
  2. 异常处理

    • 默认只对RuntimeException和Error回滚
    • 检查异常需要显式配置rollbackFor
  3. 自调用问题

    public class OrderService {
    
    
       public void placeOrder(Order order) {
           validateOrder(order);  // 这里的事务注解不会生效
           processPayment();
       }
    
    
       @Transactional
       public void validateOrder(Order order) {
           // 验证逻辑
       }
    }
    

    解决方法:

    • 将方法拆分到不同类
    • 使用AspectJ模式
  4. 性能考虑

    • 避免在事务方法中进行远程调用或复杂计算
    • 合理设置事务超时时间

7. 高级配置

7.1 多数据源事务

@Configuration
@EnableTransactionManagement
public class MultiDataSourceConfig {
    
    @Bean
    @Primary
    public PlatformTransactionManager primaryTxManager(DataSource ds1) {
        return new DataSourceTransactionManager(ds1);
    }
    
    @Bean
    public PlatformTransactionManager secondaryTxManager(DataSource ds2) {
        return new DataSourceTransactionManager(ds2);
    }
}

// 使用指定的事务管理器
@Service
public class CrossDbService {
    
    @Transactional("primaryTxManager")
    public void primaryDbOp() {...}
    
    @Transactional("secondaryTxManager")
    public void secondaryDbOp() {...}
}

7.2 完全注解配置

@SpringBootApplication
@EnableTransactionManagement
@MapperScan("com.example.mapper")
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

8. 常见问题

  1. 事务不生效

    • 检查是否启用@EnableTransactionManagement
    • 检查方法是否为public
    • 检查异常类型是否匹配
  2. 长事务问题

    • 设置合理的事务超时
    • 拆分大事务为多个小事务
  3. 连接泄露

    • 确保在事务方法内关闭所有资源
    • 使用try-with-resources语法

通过合理使用@Transactional注解,可以大大简化Spring应用中的事务管理,同时保持代码的清晰性和可维护性。 “`

推荐阅读:
  1. Spring注解 TX声明式事务实现过程解析
  2. Spring实战之使用注解实现声明式事务操作示例

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

spring

上一篇:Redis中如何使用集合类型

下一篇:MyBatis中Example如何使用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》