即使没有 @Transactional/@EnableTransactionManagement 的 JPA 事务

JPA transaction even without @Transactional/@EnableTransactionManagement

提问人:Gaetan L. 提问时间:9/25/2023 最后编辑:Ken ChanGaetan L. 更新时间:9/26/2023 访问量:92

问:

我正在尝试了解事务如何与 Spring 一起工作。我有一个扩展 CrudRepository 的存储库接口:

@Transactional
public interface MessageRepository extends CrudRepository<Message, Long> {
}

以及我用来创建 EntityManagerFactory 和 TransactionManager 的 PersistenceConfig:

@Configuration
@EnableTransactionManagement
public class PersistenceConfig {
    final static Logger logger = LoggerFactory.getLogger(PersistenceConfig.class);

    public static EntityManagerFactory emf = null;

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

    @Bean
    public EntityManagerFactory entityManagerFactory() {
        if (emf == null) {
            synchronized (EntityManagerFactory.class) {
                if (emf == null) {
                    final StandardServiceRegistry sr = new StandardServiceRegistryBuilder()
                            .configure() // Configures setting from hibernate.cfg.xml
                            .build();
                    try {
                        emf = new MetadataSources(sr).buildMetadata().buildSessionFactory();
                    }
                    catch (Exception e) {
                        StandardServiceRegistryBuilder.destroy(sr);
                        throw e;
                    }
                }
            }
        }
        return emf;
    }
}

问题是,我使用记录器来调试 JpaTransactionManager,无论我是否使用注解 @Transactional/@EnableTransactionManager,我都可以看到使用了事务:

3576 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager  - Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
3576 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager  - Opened new EntityManager [SessionImpl(2090037997<open>)] for JPA transaction
[...]
3576 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager  - Initiating transaction commit
3576 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager  - Committing JPA transaction on EntityManager [SessionImpl(2090037997<open>)]
[...]
3576 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager  - Closing JPA EntityManager [SessionImpl(2090037997<open>)] after transaction

那么,使用这些有什么意义呢?

Spring JPA spring-data-jpa spring- 事务

评论

0赞 Andrei Lisa 9/25/2023
如果要从存储库界面中删除。调用不会在事务中@Transactional
0赞 Gaetan L. 9/25/2023
@AndreiLisa但提供的日志来自我删除 @Transactional/@EnableTransactionManager 的运行。您可以清楚地看到 TransactionManager 正在使用事务。
0赞 Andrei Lisa 9/25/2023
还有您使用的是存储库中的哪种方法?
0赞 Gaetan L. 9/25/2023
每一种方法!包括保存和删除。
1赞 Andrei Lisa 9/25/2023
我会写一个关于这个问题的答案

答:

2赞 Andrei Lisa 9/25/2023 #1

当方法未使用注释显式声明时,调用事务的原因是:@Transactional

根据文档和 Java 文档

默认情况下,继承自 CrudRepository 的方法继承 来自 SimpleJpaRepository 的事务配置。供阅读 操作时,事务配置 readOnly 标志设置为 真。所有其他配置都配置了一个普通@Transactional,以便 默认事务配置适用。存储库方法 由事务存储库片段提供支持的事务性存储库片段继承事务性存储库片段 实际 fragment 方法中的属性。

要了解有关它的更多详细信息,我建议您阅读文档,主要是 5.1.7。事务性

评论

1赞 Gaetan L. 9/25/2023
明白了!太棒了,谢谢你的回答!
1赞 Ken Chan 9/25/2023 #2

默认情况下,Spring-data-jpa 将在后台对 上的每个非查询方法进行配置。这意味着即使你没有配置 / ,这些东西仍然存在,因此你会在日志中看到它们。@TransactionalCrudRepository@Transactional@EnableTransactionManagement@Transactional

您可以通过以下方式关闭此类默认行为:

@EnableJpaRepositories(enableDefaultTransactions=false)

其中具有以下含义enableDefaultTransactions

配置是否启用 Spring Data JPA 的缺省事务 存储 库。默认值为 true。如果禁用,则必须使用存储库 在配置事务的 Fave 后面(例如,使用 Spring 的 注解驱动的事务设施)或存储库方法具有 用于划分交易。

定义和自己定义的意义在于,它为您提供了更大的灵活性来定义所需的事务边界。您可以将其扩展到业务服务方法,甚至更广泛,但不仅限于存储库级别的方法。@EnableTransactionManagement@Transactional