Spring JPA 存储库事务性

Posted

技术标签:

【中文标题】Spring JPA 存储库事务性【英文标题】:Spring JPA repository transactionality 【发布时间】:2017-02-11 03:06:23 【问题描述】:

关于 的 1 个快速问题。 我有一个未标记为事务性的服务并调用 Spring JPA 存储库方法

userRegistrationRepository.deleteByEmail(email);

它被定义为

@Repository
public interface UserRegistrationRepository extends JpaRepository<UserRegistration, Long> 

    UserRegistration findByEmail(String email);

    void deleteByEmail(String email);


问题在于它失败并显示“当前线程没有具有实际事务可用的 EntityManager - 无法可靠地处理 'remove' 调用;嵌套异常是 javax.persistence.TransactionRequiredException”异常。

好的,我可以通过将服务 or deleteByEmail(..) 方法标记为事务性来解决它,但我就是不明白为什么它现在崩溃了。 Spring 文档明确指出“存储库实例上的 CRUD 方法默认情况下是事务性的。”(http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions),但显然这个不是......所以这个声明仅与 @987654324 的成员有关@?

ps:那是 Spring Data JPA 1.9.4

【问题讨论】:

【参考方案1】:

你是对的。默认情况下,只有 CRUD 方法(CrudRepository 方法)被标记为事务性的。 如果您使用自定义查询方法,则应使用 @Transactional 注释显式标记它。

@Repository
public interface UserRegistrationRepository extends JpaRepository<UserRegistration, Long> 

    UserRegistration findByEmail(String email);

    @Transactional
    void deleteByEmail(String email);


您还应该注意标记存储库接口方法而不是服务方法的后果。如果您使用默认事务传播配置 (Propagation.REQUIRED),则:

存储库中的事务配置将被忽略 然后作为外部事务配置确定实际的 用过。

http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions

如果您想了解有关它如何实现的更多信息,请查看默认的 CrudRepository / JpaRepository 实现 - SimpleJpaRepository(您可能正在使用):

https://github.com/spring-projects/spring-data-jpa/blob/master/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java

有趣的台词在这里:

@Transactional(readOnly = true)
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> 

这里还有一些事务方法:

@Transactional
public void deleteById(ID id) 
@Transactional
public <S extends T> S save(S entity) 

【讨论】:

在 spring-data-jpa:2.0.9 中,JpaRepository 或其祖先的源代码中没有 @Transactional 注释 - 默认事务性似乎在运行时应用。另请注意,如果您将@Transactional( ... custom properties ... ) 放在您的存储库接口上,它将适用于在您的接口和子接口中声明的所有方法——但不适用于在父接口 (JpaRepository) 中声明的任何方法,除非您重新声明它们. @AndrewSpencer @Transactional 注释默认应用JpaRepository / CrudRepository 实现:SimpleJpaRepository 看这里:github.com/spring-projects/spring-data-jpa/blob/master/src/main/… 我想你会在那里找到所有答案:) 感谢您的更正 - 这不是运行时魔法,只是注释的实现类。不过,我关于覆盖的评论仍然是准确的。

以上是关于Spring JPA 存储库事务性的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA + Hibernate 将方法标记为事务

Spring跨越方法的JPA事务

Spring 4.3.0.RELEASE + Hibernate 5.2.0.Final + JPA 存储库

Spring JPA Repository findAll 在 JUnit 测试中不返回任何数据

Spring Data Jpa问题在一个事务中保存父,子和childofchild

Spring 单元测试 JPA 存储库