如何将 @Transactional 与 Spring Data 一起使用?

2022-01-18 00:00:00 spring java jpa spring-data spring-data-jpa

我刚开始从事 Spring-data、Hibernate、MySQL、JPA 项目.我切换到 spring-data 这样我就不必担心手动创建查询了.

I just started working on a Spring-data, Hibernate, MySQL, JPA project. I switched to spring-data so that I wouldn't have to worry about creating queries by hand.

我注意到,当您使用 spring-data 时,不需要使用 @Transactional,因为我也尝试了没有注释的查询.

I noticed that the use of @Transactional isn't required when you're using spring-data since I also tried my queries without the annotation.

我应该/不应该使用 @Transactional 注释有什么具体原因吗?

Is there a specific reason why I should/shouldn't be using the @Transactional annotation?

作品:

@Transactional
public List listStudentsBySchool(long id) {
    return repository.findByClasses_School_Id(id);
}

同样有效:

public List listStudentsBySchool(long id) {
    return repository.findByClasses_School_Id(id);
}

提前致谢!

推荐答案

你的问题实际上是关于什么的?@Repository 注释或 @Transactional 的用法.

What is your question actually about? The usage of the @Repository annotation or @Transactional.

@Repository 根本不需要,因为您声明的接口将由 Spring Data 基础架构创建并激活异常转换的代理支持.所以在 Spring Data 存储库接口上使用这个注解根本没有任何效果.

@Repository is not needed at all as the interface you declare will be backed by a proxy the Spring Data infrastructure creates and activates exception translation for anyway. So using this annotation on a Spring Data repository interface does not have any effect at all.

@Transactional - 对于 JPA 模块,我们在支持代理的实现类上有这个注解 (SimpleJpaRepository).这有两个原因:首先,持久化和删除对象需要 JPA 中的事务.因此,我们需要确保事务正在运行,我们通过使用 @Transactional 注释方法来做到这一点.

@Transactional - for the JPA module we have this annotation on the implementation class backing the proxy (SimpleJpaRepository). This is for two reasons: first, persisting and deleting objects requires a transaction in JPA. Thus we need to make sure a transaction is running, which we do by having the method annotated with @Transactional.

findAll()findOne(…) 等读取方法正在使用 @Transactional(readOnly = true),这不是绝对必要的,但触发事务基础结构中的一些优化(将 FlushMode 设置为 MANUAL 以让持久性提供程序在关闭 EntityManager 时可能跳过脏检查).除此之外,该标志也在 JDBC 连接上设置,这会导致该级别的进一步优化.

Reading methods like findAll() and findOne(…) are using @Transactional(readOnly = true) which is not strictly necessary but triggers a few optimizations in the transaction infrastructure (setting the FlushMode to MANUAL to let persistence providers potentially skip dirty checks when closing the EntityManager). Beyond that the flag is set on the JDBC Connection as well which causes further optimizations on that level.

根据您使用的数据库,它可以忽略表锁,甚至拒绝您可能意外触发的写入操作.因此,我们建议将 @Transactional(readOnly = true) 用于查询方法,您可以轻松地实现将注释添加到存储库接口.确保将纯 @Transactional 添加到您可能在该接口中声明或重新装饰的操作方法.

Depending on what database you use it can omit table locks or even reject write operations you might trigger accidentally. Thus we recommend using @Transactional(readOnly = true) for query methods as well which you can easily achieve adding that annotation to you repository interface. Make sure you add a plain @Transactional to the manipulating methods you might have declared or re-decorated in that interface.

相关文章