Java声明事务案例如何配置

wen java案例 24

本文目录导读:

Java声明事务案例如何配置

  1. Spring Boot 注解方式(最常用)
  2. 传统 Spring XML 配置方式
  3. @Transactional 重要参数说明
  4. 常见注意事项

在Java中声明事务通常有两种主流方式:注解方式(推荐)和XML配置方式,下面我按照Spring Boot + Spring Data JPA传统Spring XML两种场景,给你完整的配置案例。

Spring Boot 注解方式(最常用)

Spring Boot 只要引入了相关依赖,事务基本是“开箱即用”的,但需要显式开启事务管理。

添加依赖(pom.xml)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

配置数据源和JPA(application.yml)

spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
    username: sa
    password:
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    database-platform: org.hibernate.dialect.H2Dialect

开启事务管理(Application主类)

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableTransactionManagement  // 显式开启事务管理(Spring Boot 会自动配置,但显式写出来更清晰)
public class TransactionDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(TransactionDemoApplication.class, args);
    }
}

注意@EnableTransactionManagement 在 Spring Boot 中不是必须的,它默认已经自动配置了,但如果你需要自定义事务管理器,则需要显式使用。

实体类(User.java)

import javax.persistence.*;
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private Integer age;
    // getters and setters 省略
}

Repository

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

Service 层使用 @Transactional

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    // 方法级别:这个方法内所有数据库操作在同一个事务中
    @Transactional
    public void transferMoney(Long fromUserId, Long toUserId, Integer amount) {
        User from = userRepository.findById(fromUserId).orElseThrow();
        User to = userRepository.findById(toUserId).orElseThrow();
        from.setAge(from.getAge() - amount); // 模拟扣钱
        to.setAge(to.getAge() + amount);     // 模拟加钱
        userRepository.save(from);
        userRepository.save(to);
        // 如果这里抛出异常,上述两个操作都会回滚
    }
    // 类级别:整个类的所有public方法都默认有事务
    @Transactional(readOnly = true)  // 只读事务,提高性能
    public User getUserById(Long id) {
        return userRepository.findById(id).orElse(null);
    }
}

Controller 调用验证

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserService userService;
    @PostMapping("/transfer")
    public String transfer(@RequestParam Long from, @RequestParam Long to, @RequestParam Integer amount) {
        try {
            userService.transferMoney(from, to, amount);
            return "转账成功";
        } catch (Exception e) {
            return "转账失败: " + e.getMessage();
        }
    }
}

传统 Spring XML 配置方式

如果你还在使用传统的 Spring XML 配置项目,配置如下:

配置数据源、事务管理器(applicationContext.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!-- 1. 数据源 -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>
    <!-- 2. JPA 实体管理工厂 -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="packagesToScan" value="com.example.entity"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>
    <!-- 3. 事务管理器 -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    <!-- 4. 开启注解事务管理 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

Service 层使用注解(同 Spring Boot 方式)

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    @Transactional
    public void transferMoney(Long fromId, Long toId, Integer amount) {
        // ... 业务逻辑
    }
}

@Transactional 重要参数说明

参数 说明 默认值
propagation 事务传播行为 Propagation.REQUIRED
isolation 事务隔离级别 Isolation.DEFAULT
timeout 超时时间(秒) -1(不超时)
readOnly 是否只读事务 false
rollbackFor 指定哪些异常触发回滚 运行时异常(RuntimeException)
noRollbackFor 指定哪些异常不触发回滚

示例:

@Transactional(
    propagation = Propagation.REQUIRED,
    isolation = Isolation.READ_COMMITTED,
    timeout = 30,
    rollbackFor = {Exception.class},
    readOnly = false
)
public void someMethod() {
    // ...
}

常见注意事项

  1. @Transactional 只能用在 public 方法上,private 或 protected 无效。
  2. 自身调用失效:同一个类中方法 A(无事务)调用方法 B(有事务),B 的事务不会生效(需要注入代理对象)。
  3. 异常回滚:默认只对 RuntimeExceptionError 回滚,如果希望 checked exception 也回滚,需要设置 rollbackFor = Exception.class
  4. 只读事务:查询操作建议设置 readOnly = true,可以提高性能。

如果你有具体的框架(如 Spring Cloud、MyBatis)或场景(如分布式事务)需求,可以进一步补充,我可以给你更针对性的配置。

抱歉,评论功能暂时关闭!