目录
1. 概述
促进阅读:
2. 配置不带 xml 的事务
3. 使用 xml 配置事务
4. @Transactional 注解
5. 潜在的陷阱
5.1. 事务和代理
5.2. 更改隔离级别
5.3. 只读事务
5.4. 事务日志记录
6. 结论
1. 概述
本文将讨论 配置 Spring Transactions 的正确方法, 如何使用 @Transactional 注解和常见陷阱.
有关核心持久性配置的更深入讨论, 请查看 Spring JPA 教程.
通常, 有两种不同的方式来配置事务: 注解和 AOP,
每个都有自己的优势. 我们将在这里讨论更常见的注解配置.
促进阅读:
为测试配置单独的 Spring DataSource
有关在 Spring 应用程序中配置单独数据源以进行测试的快速实用教程.
更多 →
使用 Spring Boot 加载初始数据的快速指南
在 Spring Boot 中使用 data.sql 和 schema.sql 文件的快速实用示例.
更多 →
从 Spring Boot 显示 Hibernate / JPA SQL 语句 https://www.baeldung.com/sql-logging-spring-boot
了解如何在 Spring Boot 应用程序中配置生成的 SQL 语句的日志记录.
更多 https://www.baeldung.com/sql-logging-spring-boot →
2. 配置不带 xml 的事务
Spring 3.1 引入了 @EnableTransactionManagement 注释, 我们可以在 @Configuration 类中使用并启用事务支持:
- @Configuration
- @EnableTransactionManagement
- public class PersistenceJPAConfig{
- @Bean
- public LocalContainerEntityManagerFactoryBean
- entityManagerFactoryBean(){
- //...
- }
- @Bean
- public PlatformTransactionManager transactionManager(){
- JpaTransactionManager transactionManager
- = new JpaTransactionManager();
- transactionManager.setEntityManagerFactory(
- entityManagerFactoryBean().getObject() );
- return transactionManager;
- }
- }
但是, 如果我们使用 Spring Boot 项目, 并且在 classpath 上具有 spring-data- * 或 spring-tx 依赖项, 则默认情况下将启用事务管理.
3. 使用 xml 配置事务
在 3.1 之前通常使用 annotation-driven namespace:
- <bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
- <property name="entityManagerFactory" ref="myEmf" />
- </bean>
- <tx:annotation-driven transaction-manager="txManager" />
4. @Transactional 注解
通过配置事务, 我们可以在 bean 的类和方法上使用 @Transactional 注解:
- @Service
- @Transactional
- public class FooService {
- //...
- }
注解还支持进一步配置:
事务的转播类型
事务的隔离级别
事务包装操作的超时
只读标志 - 提示持久性事务只读
事务的回滚规则
请注意 - 默认情况下, 仅对 runtime,unchecked 的异常进行回滚. checked 异常不会触发事务的回滚. 当然, 我们可以使用 rollbackFor 和 noRollbackFor 注解来配置异常回滚.
5. 潜在的陷阱
5.1. 事务和代理
在较高的层次上, spring 为所有用 @transactional 注解的类创建代理, 无论是在类上还是在方法上. 代理允许框架在运行方法之前和之后注入事务逻辑, 主要用于启动和提交事务.
重要的是, 如果正在实现事务 bean 的接口, 默认情况下代理将是 Java 动态代理. 这意味着只会拦截通过代理进入的外部方法调用. self-invocation 调用时即使方法有 @transactional 注解也不会启用事务.
使用代理的另一个注意事项是只有 public 方法才能用 @transactional 注解, 在其他任何可见性的方法上进行注解时, 这些方法都是没有代理的, 因为他们会忽略掉这些注解.
这里有详细的代理陷阱
5.2. 更改隔离级别
我们可以通过以下代码做事务隔离级别更改:
@Transactional(isolation = Isolation.SERIALIZABLE)
已经在 Spring4.1 中 引入 https://jira.spring.io/browse/SPR-5012 ; 如果我们在 Spring4.1 之前的版本上配置隔离级别:
org.springframework.transaction.InvalidIsolationLevelException: Standard JPA does not support custom isolation levels - use a special JpaDialect for your JPA implementation
5.3. 只读事务
readonly 标志通常会产生混淆, 尤其是在使用 JPA 时, 以下来自 Javadoc:
This just serves as a hint for the actual transaction subsystem; it will not necessarily cause failure of write access attempts. A transaction manager which cannot interpret the read-only hint will not throw an exception when asked for a read-only transaction.
实际上设置 readOnly 标志后, 并不能确定不会发生插入或更新.
同样 readOnly 标志只在事务中有用. 如果在事务上下文之外, 将会忽略这个标志:
@Transactional( propagation = Propagation.SUPPORTS,readOnly = true )
将会忽略 readOnly 标志
5.4. 事务日志记录
理解事务相关问题的最有效方法是对事务包中的日志进行调试.
可以设置 "org.springframework.transaction" 的日志级别为 "TRACE".
6. 结论
使用 Java 和 xml 来介绍事务的基本配置, 以及 @Transactional 的使用.
GitHub.
来源: https://www.cnblogs.com/alterem/p/11463452.html