【Spring】4.Spring的事务管理解析

本文介绍了事务在数据库管理系统中的重要性,特别是Spring框架中的事务处理,包括声明式和编程式两种方式,详细阐述了ACID属性以及如何配置事务的属性和行为。
摘要由CSDN通过智能技术生成

什么是事务

事务是数据库管理系统中的一个关键概念,用于确保数据的完整性和可靠性。在Spring框架中,事务通常指的是一段代码,这段代码要么完全执行,要么完全不执行,不会出现部分执行的情况。 Spring提供了事务管理的机制,允许开发者以声明式或编程式的方式来控制事务的边界和行为。

事务具有ACID属性,这确保了事务的可靠性:

  1. 原子性(Atomicity):事务中的所有操作要么全部完成,要么全部不完成,不会结束在中间某个点。
  2. 一致性(Consistency):事务必须使数据库从一个一致的状态转移到另一个一致的状态。
  3. 隔离性(Isolation):并发执行的事务之间不会互相影响,每个事务都像是独立执行。
  4. 持久性(Durability):一旦事务提交,则其结果永久保存在数据库中,即使系统发生故障也不会丢失。

Spring的事务管理主要有两种方式:

事务管理

1.声明式事务管理:

通过配置文件或注解来声明事务的边界和特性,利用AOP(面向切面编程)在方法执行前后添加事务管理的逻辑。
在Spring Boot中实现声明式事务管理,涉及到自动配置、自定义配置、事务属性的设置等多个方面。以下是详细的步骤和配置方法:

1. 添加依赖

确保项目中包含了Spring Boot的事务管理和数据库相关依赖。对于JPA,依赖如下:

Maven (pom.xml):

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <!-- 数据库驱动依赖,例如MySQL -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <!-- 其他业务依赖 -->
</dependencies>

Gradle (build.gradle):

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'mysql:mysql-connector-java'
    // 其他业务依赖
}

2. 配置数据源

application.propertiesapplication.yml中配置数据库连接信息:

# application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/your_db?useSSL=false
spring.datasource.username=your_username
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

3. 配置实体扫描

创建一个配置类,用于指定实体类的扫描路径,以及配置事务管理器:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    entityManagerFactoryRef = "entityManagerFactory",
    transactionManagerRef = "transactionManager",
    basePackages = {"com.example.domain"} // 实体类的包
)
public class DatabaseConfig {

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            EntityManagerFactoryBuilder builder, DataSource dataSource) {
        return builder
                .dataSource(dataSource)
                .packages("com.example.domain") // 实体类的包
                .persistenceUnit("default")
                .build();
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

4. 使用@Transactional注解

在需要事务管理的类或方法上使用@Transactional注解:

@Service
public class SomeService {

    @Autowired
    private SomeRepository someRepository;

    @Transactional
    public void someServiceMethod() {
        // 业务逻辑,涉及数据库操作
        someRepository.doSomething();
    }
}

5. 配置事务属性

通过@Transactional注解的属性来配置传播行为、隔离级别、超时时间、只读属性和回滚规则:

@Transactional(
    propagation = Propagation.REQUIRED,
    isolation = Isolation.READ_COMMITTED,
    timeout = 30, // 超时时间,单位为秒
    readOnly = false,
    rollbackFor = Exception.class // 指定哪些异常会导致事务回滚
)
public void someServiceMethod() {
    // 业务逻辑
}

6. 自定义事务管理器

如果需要自定义事务管理器,可以在配置类中添加相应的@Bean方法:

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory);
    // 可以在这里设置其他属性,如超时时间
    return transactionManager;
}

7. 配置事务管理器属性

通过配置文件设置事务管理器的属性,例如JPA的事务超时时间:

# application.properties
spring.jpa.properties.hibernate.transaction.manager_lookup_class=org.hibernate.hql.internal.TransactionManagerLookup
spring.transaction.default_timeout=5 # 以秒为单位设置默认的事务超时时间

8. 多数据源事务管理

如果应用中使用了多个数据源,需要为每个数据源配置独立的事务管理器,并在@EnableJpaRepositories注解中指定事务管理器和实体管理器工厂:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    entityManagerFactoryRef = "entityManagerFactorySecondary",
    transactionManagerRef = "transactionManagerSecondary",
    basePackages = {"com.example.domain.secondary"}
)
public class SecondaryDatabaseConfig {

    @Bean(name = "entityManagerFactorySecondary")
    public LocalContainerEntityManagerFactoryBean getEntityManagerFactorySecondary() {
        // 配置第二个数据源的EntityManagerFactoryBean
    }

    @Bean(name = "transactionManagerSecondary")
    public PlatformTransactionManager getTransactionManagerSecondary(EntityManagerFactory entityManagerFactory) {
        // 配置第二个数据源的JpaTransactionManager
    }
}

通过上述步骤,就可以在Spring Boot应用中实现声明式事务管理了,并且可以根据业务需求配置不同的事务属性。Spring Boot的自动配置功能会根据你添加的依赖和配置来自动配置Spring的事务管理器,从而简化了事务管理的复杂性。

2.编程式事务管理:

通过代码直接管理事务的生命周期,如获取和释放事务资源,提交或回滚事务等。
在Spring Boot中实现编程式事务管理,你需要使用TransactionTemplate类。Spring Boot的自动配置机制会为你配置好事务管理器,但编程式事务管理不会自动应用,你需要显式地在你的代码中使用TransactionTemplate

以下是在Spring Boot中实现编程式事务管理的步骤:

1. 配置事务管理器

Spring Boot通常会自动配置事务管理器,但如果你想自定义配置,可以在配置类中添加一个PlatformTransactionManager的Bean。例如,如果你使用的是JPA,Spring Boot会默认配置一个JpaTransactionManager

Java配置示例

@Configuration
public class DatabaseConfig {

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, DataSource dataSource) {
        return builder
                .dataSource(dataSource)
                .packages("com.example.domain") // 指定实体类所在的包
                .persistenceUnit("default")
                .build();
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

2. 配置TransactionTemplate

在你的配置类或服务类中,创建一个TransactionTemplate的Bean,并注入你之前配置的PlatformTransactionManager

Java配置示例

@Service
public class SomeService {

    @Autowired
    private TransactionTemplate transactionTemplate; // Spring Boot会自动注入

    public void someServiceMethod() {
        // 使用TransactionTemplate执行事务
        transactionTemplate.execute(status -> {
            // 这里编写业务逻辑
            // 这些操作将被事务管理
            return null;
        });
    }
}

3. 设置事务属性

通过TransactionTemplateexecute方法,你可以传递一个TransactionStatus的回调。虽然你不能直接设置传播行为和隔离级别,但你可以在事务管理器的配置中设置这些属性。

例如,对于DataSourceTransactionManager,你可以设置默认的隔离级别:

@Bean
public DataSourceTransactionManager transactionManager(DataSource dataSource) {
    DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
    transactionManager.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
    return transactionManager;
}

4. 适应不同的业务场景

  • 读取操作:对于读取操作,如果不需要事务管理,可以使用PROPAGATION_NOT_SUPPORTEDPROPAGATION_NEVER
  • 写入操作:对于写入操作,默认使用PROPAGATION_REQUIRED
  • 嵌套事务:对于需要嵌套事务的场景,可以使用PROPAGATION_NESTED

由于编程式事务管理不使用注解,因此事务的传播行为和隔离级别通常在事务管理器的配置中设置。如果你需要更细粒度的控制,可能需要考虑使用声明式事务管理。
在Spring Boot中,推荐使用声明式事务管理,因为它更符合Spring的编程模型,并且易于使用。编程式事务管理通常用于那些不能使用声明式事务管理的场景。

3.事务的属性

在Spring框架中,事务属性定义了事务的特定行为,包括其传播行为、隔离级别、超时设置、只读标志以及回滚规则。以下是Spring支持的主要事务属性:

1. 传播行为(Propagation Behavior)

  • REQUIRED:如果存在一个事务,则加入该事务;如果不存在事务,则创建一个新的事务。
  • SUPPORTS:支持当前事务,如果没有事务则不创建。
  • MANDATORY:必须在一个事务中,否则抛出异常。
  • REQUIRES_NEW:总是创建一个新的事务。
  • NOT_SUPPORTED:不能在事务中执行,如果存在一个活动的事务,则将其挂起。
  • NESTED:如果支持嵌套事务,就创建一个嵌套事务。如果当前事务存在,则嵌套事务是当前事务的子事务。

2. 隔离级别(Isolation Level)

  • ISOLATION_DEFAULT:使用后端数据库的默认隔离级别。
  • ISOLATION_READ_UNCOMMITTED:读未提交。
  • ISOLATION_READ_COMMITTED:读已提交。
  • ISOLATION_REPEATABLE_READ:重复读。
  • ISOLATION_SERIALIZABLE:串行化。

3. 超时属性(Timeout)

  • 以秒为单位设置事务的超时时间。超过这个时间,事务将被回滚。

4. 只读属性(Read-Only)

  • 标记事务为只读事务,这可以给某些事务管理器提供优化的机会。

5. 回滚规则(Rollback Rules)

  • 定义哪些异常会导致事务回滚。可以使用rollbackFornoRollbackFor属性指定。

6. Phase(事务的阶段)

  • 指定事务应该在方法的执行阶段(例如,方法调用之前、调用之后、方法返回时或抛出异常时)。

7. 异步执行(Asynchronous Execution)

  • 在某些事务管理器中,可以配置事务的异步执行。

这些属性可以通过编程式事务管理或声明式事务管理来设置。在声明式事务管理中,通常使用@Transactional注解来设置这些属性,而在编程式事务管理中,则通过TransactionDefinition对象来设置。正确配置事务属性对于确保数据的一致性、隔离性和整体事务管理策略至关重要。理解这些属性及其对事务行为的影响是进行事务管理的关键。

工作原理

Spring中@Transactional注解的工作原理可以概括为以下几个步骤:

1. 注解驱动的事务管理启用

在Spring配置中通过@EnableTransactionManagement注解启用事务管理,这将使得Spring扫描并处理@Transactional注解。

2. 事务属性的配置

使用@Transactional注解标记方法或类,通过注解的参数定义事务的属性,如传播行为、隔离级别、超时时间、只读标志、回滚规则等。

3. 创建代理

Spring容器在创建Bean时,会检测到@Transactional注解。对于被注解的方法,Spring会通过AOP创建一个代理对象(可能是JDK动态代理或CGLIB代理),原始方法的调用会被这个代理对象所包装。

4. 代理对象的调用

当调用一个被@Transactional注解的方法时,实际上是调用了代理对象中的方法。在代理对象内部,Spring框架会在方法执行前后添加事务逻辑。

5. 事务的开始

在代理对象的方法调用之前,Spring会根据定义的事务属性开始一个新的事务或加入到已存在的事务中。

6. 业务逻辑的执行

执行被@Transactional注解的方法中的业务逻辑。

7. 事务的提交或回滚

  • 如果方法正常执行完成,Spring将提交事务。
  • 如果方法执行过程中抛出异常,并且该异常没有被注解的rollbackFor属性排除在外,Spring将回滚事务。

8. 清理

事务完成后,无论是提交还是回滚,Spring都会完成事务的清理工作,包括释放数据库连接等资源。

9. 事务管理器

在整个过程中,PlatformTransactionManager是一个关键的组件,它负责实际的事务管理操作,如获取TransactionStatus,以及根据运行时情况提交或回滚事务。

通过这个流程,@Transactional注解使得Spring能够以声明式的方式管理事务,让开发者可以专注于业务逻辑,而不必显式地处理事务的创建、提交和回滚。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值