事务和Spring常用注解
一、事务(Transaction)
在Spring中,事务管理主要通过PlatformTransactionManager接口实现,该接口有不同的实现类,如DataSourceTransactionManager(用于JDBC和MyBatis)、HibernateTransactionManager(用于Hibernate)等。
- 事务特性(ACID)
原子性(Atomicity):事务是一个不可分割的操作单元,要么全部成功,要么全部失败。
一致性(Consistency):事务执行前后,数据库状态必须保持一致。
隔离性(Isolation):多个并发事务之间互不干扰。
持久性(Durability):事务一旦提交,其结果就是永久性的。 - 事务传播行为(Propagation)
在Spring中,事务传播行为定义了多个事务方法相互调用时,事务如何传播。常用的传播行为有:
REQUIRED(默认):如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。
MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则挂起当前事务。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则挂起当前事务。
NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则创建一个新的事务。
3. 事务隔离级别(Isolation)
DEFAULT:使用底层数据库的默认隔离级别。
READ_UNCOMMITTED:最低的隔离级别,允许读取未提交的数据变更,可能会导致脏读、幻读或不可重复读。
READ_COMMITTED:允许读取并发事务已经提交的数据,可以防止脏读,但幻读和不可重复读仍可能发生。
REPEATABLE_READ:对同一字段的多次读取结果都是一致的,除非数据被本事务修改,可以防止脏读和不可重复读,但幻读仍可能发生。
SERIALIZABLE:最高的隔离级别,完全服从ACID的隔离级别,防止脏读、不可重复读和幻读。
4. 事务超时(Timeout)
事务执行的最长时间,超过该时间事务自动回滚。
- 只读事务(ReadOnly)
声明为只读的事务,可以提供优化,如数据库可以应用只读优化。
二、Spring常用注解
- 声明式事务注解
@Transactional:用于声明事务,可以应用在类或方法上。如果应用在类上,表示该类的所有公共方法都应用该事务属性。主要属性包括:
propagation:事务传播行为(可选,默认REQUIRED)
isolation:事务隔离级别(可选,默认DEFAULT)
timeout:事务超时时间(可选,默认-1,即不超时)
readOnly:是否为只读事务(可选,默认false)
rollbackFor:触发回滚的异常类型(可选)
noRollbackFor:不触发回滚的异常类型(可选)
示例:
java
Copy Code
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED,
timeout = 30, rollbackFor = Exception.class)
public void createUser(User user) {
userRepository.save(user);
}
}
2. Spring核心注解
@Component:通用注解,用于标注Spring管理的Bean。
@Service:标注业务层组件。
@Repository:标注数据访问层(DAO)组件,同时具有将数据库操作抛出的原生异常转换为Spring的DataAccessException的作用。
@Controller:标注控制层组件(如Spring MVC中的控制器)。
@RestController:组合注解,相当于@Controller和@ResponseBody的组合,用于构建RESTful Web服务。
@Autowired:自动装配,根据类型(byType)自动注入依赖。
@Qualifier:与@Autowired配合使用,当存在多个相同类型的Bean时,通过名称(byName)指定注入的Bean。
@Resource:JSR-250提供的注解,默认按名称(byName)自动注入,也可以指定名称或类型。
@Value:注入属性值,可以注入配置文件中的值。
@Configuration:标注配置类,相当于XML配置文件。
@Bean:在配置类中标注方法,该方法返回一个Bean,并交给Spring容器管理。
@ComponentScan:配置组件扫描的包。
@PropertySource:加载指定的属性文件(.properties)到Spring的Environment中。
@ConfigurationProperties:将配置文件中的属性绑定到Java对象中(通常是一个POJO)。
@Scope:指定Bean的作用域(singleton、prototype、request、session等)。
3. Spring MVC相关注解
@RequestMapping:映射HTTP请求到控制器方法,可以指定URL、请求方法、请求参数等。
@GetMapping、@PostMapping、@PutMapping、@DeleteMapping等:分别对应HTTP的GET、POST、PUT、DELETE等方法的映射。
@PathVariable:将URL中的模板变量绑定到方法的参数上。
@RequestParam:将请求参数绑定到方法的参数上。
@RequestBody:将HTTP请求体(JSON或XML等)绑定到方法的参数上(通常用于接收前端传来的JSON数据)。
@ResponseBody:将方法返回的对象序列化为JSON或XML等格式,并写入HTTP响应体。
@ModelAttribute:将请求参数绑定到模型对象上,或者将方法返回值添加到模型对象中。
@SessionAttribute:将模型对象存储在会话中。
@RequestHeader:将请求头信息绑定到方法的参数上。
@CookieValue:将Cookie的值绑定到方法的参数上。
@ExceptionHandler:处理控制器中方法抛出的异常。
@ControllerAdvice:定义全局异常处理、全局数据绑定、全局数据预处理等。
4. 条件注解
@Conditional:根据特定条件创建Bean。
@Profile:根据当前激活的配置文件(profile)决定是否创建Bean。
5. 异步与调度
@Async:标注方法为异步方法,调用时会异步执行。
@EnableAsync:开启异步任务支持。
@Scheduled:标注方法为定时任务。
@EnableScheduling:开启定时任务支持。
三、示例代码
下面是一个使用事务和常用注解的简单示例:
配置类:
java
Copy Code
@Configuration
@ComponentScan(basePackages = "com.example")
@EnableTransactionManagement // 开启事务管理
@PropertySource("classpath:application.properties")
public class AppConfig {
// 配置数据源等,这里省略
}
服务层使用事务:
java
Copy Code
@Service
public class AccountService {
@Autowired
private AccountRepository accountRepository;
@Transactional
public void transferMoney(Long fromAccountId, Long toAccountId, Double amount) {
Account fromAccount = accountRepository.findById(fromAccountId).orElseThrow();
Account toAccount = accountRepository.findById(toAccountId).orElseThrow();
fromAccount.setBalance(fromAccount.getBalance() - amount);
toAccount.setBalance(toAccount.getBalance() + amount);
accountRepository.save(fromAccount);
accountRepository.save(toAccount);
}
}
在控制器中调用服务:
java
Copy Code
@RestController
@RequestMapping("/accounts")
public class AccountController {
@Autowired
private AccountService accountService;
@PostMapping("/transfer")
public ResponseEntity<String> transfer(@RequestParam Long from, @RequestParam Long to, @RequestParam Double amount) {
accountService.transferMoney(from, to, amount);
return ResponseEntity.ok("Transfer successful");
}
}
四、注意事项
事务失效的场景:在同一个类中,一个非事务方法调用另一个事务方法,事务会失效(因为Spring事务是基于代理的,自调用不会经过代理对象)。可以通过将事务方法移到另一个类中,或使用AspectJ的编译时/加载时织入来解决。
异常回滚:默认情况下,Spring事务只对运行时异常(RuntimeException)和错误(Error)进行回滚。检查异常(Checked Exception)不回滚。可以通过rollbackFor属性指定需要回滚的异常。
事务嵌套:正确使用传播行为,避免事务嵌套导致的问题。
以上是对事务和Spring常用注解的总结。希望能帮助你理解。
事务(Transaction)与 Spring 常用注解详解
一、事务(Transaction)
事务是数据库操作的逻辑单元,满足 ACID 特性:
原子性(Atomicity):操作要么全成功,要么全失败。
一致性(Consistency):事务前后数据状态一致。
隔离性(Isolation):并发事务互不干扰。
持久性(Durability):事务提交后数据永久保存。
Spring 事务管理
Spring 通过 @Transactional 注解实现声明式事务:
java
Copy Code
@Transactional(
propagation = Propagation.REQUIRED, // 传播行为(默认)
isolation = Isolation.DEFAULT, // 隔离级别(默认)
timeout = 30, // 超时时间(秒)
readOnly = false, // 是否只读
rollbackFor = Exception.class, // 触发回滚的异常
noRollbackFor = NullPointerException.class // 不触发回滚的异常
)
public void businessMethod() {
// 业务逻辑
}
1. 传播行为(Propagation)
类型 说明
REQUIRED (默认) 当前有事务则加入,无则新建
REQUIRES_NEW 新建事务,挂起当前事务
SUPPORTS 有事务则加入,无则以非事务执行
NOT_SUPPORTED 以非事务执行,挂起当前事务
MANDATORY 必须有事务,否则抛异常
NEVER 必须无事务,否则抛异常
NESTED 嵌套事务(依赖 JDBC 3.0)
2. 隔离级别(Isolation)
级别 说明
DEFAULT 使用数据库默认级别
READ_UNCOMMITTED 读未提交(可能脏读)
READ_COMMITTED 读已提交(避免脏读)
REPEATABLE_READ 可重复读(避免不可重复读)
SERIALIZABLE 串行化(避免幻读)
二、Spring 常用注解
1. 核心容器注解
注解 作用
@Component 通用组件标记
@Service 业务逻辑层组件
@Repository 数据访问层组件(自动转换异常)
@Controller Web 控制器组件
@Autowired 按类型自动注入依赖
@Qualifier("name") 按名称限定注入的 Bean
@Value("${prop}") 注入配置文件属性
@Configuration 标记配置类(替换 XML)
@Bean 声明方法返回的 Bean
@Scope("prototype") 指定 Bean 作用域(单例/原型等)
@Lazy 延迟初始化 Bean
2. Spring MVC 注解
注解 作用
@RequestMapping 映射 HTTP 请求到方法
@GetMapping / @PostMapping 简化请求方法映射
@PathVariable 获取 URL 路径变量
@RequestParam 获取请求参数
@RequestBody 解析请求体为对象(如 JSON)
@ResponseBody 返回结果直接写入响应体
@RestController @Controller + @ResponseBody
@ExceptionHandler 处理控制器内的异常
@ModelAttribute 绑定参数到模型对象
3. 事务与切面注解
注解 作用
@EnableTransactionManagement 启用声明式事务
@Transactional 声明事务(类/方法级)
@Aspect 声明切面类
@Before / @After 定义通知(Advice)
@Pointcut 定义切点表达式
4. 条件注解与配置
注解 作用
@ConditionalOnClass 类路径存在指定类时生效
@Profile("dev") 指定配置在特定环境激活
@PropertySource 加载外部配置文件
@ConfigurationProperties 批量绑定配置属性到 Bean
三、代码示例
1. 事务使用
java
Copy Code
@Service
public class OrderService {
@Autowired
private PaymentService paymentService;
@Transactional(rollbackFor = PaymentException.class)
public void placeOrder(Order order) {
// 保存订单
saveOrder(order);
// 支付(若失败则回滚订单)
paymentService.processPayment(order);
}
}
2. 属性注入
java
Copy Code
@Component
public class DataSourceConfig {
@Value("${db.url}")
private String url;
@Value("${db.timeout:30}") // 默认值 30
private int timeout;
}
3. REST 接口
java
Copy Code
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
User savedUser = userService.save(user);
return ResponseEntity.created(URI.create("/users/" + savedUser.getId())).body(savedUser);
}
}
四、事务失效的常见场景
方法非 public:@Transactional 对非 public 方法无效。
自调用问题:同一类中 A 方法调用 B 方法(即使 B 有 @Transactional),事务不生效。
异常被捕获:事务方法内捕获异常未重新抛出。
异常类型不匹配:默认只回滚 RuntimeException 和 Error。
数据库引擎不支持:如 MyISAM 不支持事务。
总结
事务:通过 @Transactional 配置传播行为、隔离级别等。
常用注解:核心容器(@Service, @Autowired)、MVC(@RestController, @RequestBody)、配置(@Value, @ConfigurationProperties)等。
最佳实践:事务注解标注在接口实现类或 public 方法上,避免自调用问题。

浙公网安备 33010602011771号