本文目录导读:

在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() {
// ...
}
常见注意事项
- @Transactional 只能用在 public 方法上,private 或 protected 无效。
- 自身调用失效:同一个类中方法 A(无事务)调用方法 B(有事务),B 的事务不会生效(需要注入代理对象)。
- 异常回滚:默认只对 RuntimeException 和 Error 回滚,如果希望 checked exception 也回滚,需要设置
rollbackFor = Exception.class。 - 只读事务:查询操作建议设置
readOnly = true,可以提高性能。
如果你有具体的框架(如 Spring Cloud、MyBatis)或场景(如分布式事务)需求,可以进一步补充,我可以给你更针对性的配置。