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

关于 Spring JPA 存储库事务性的 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

【问题讨论】:

    标签: java jpa spring-data spring-transactions


    【解决方案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/… 我想你会在那里找到所有答案:)
    • 感谢您的更正 - 这不是运行时魔法,只是注释的实现类。不过,我关于覆盖的评论仍然是准确的。
    猜你喜欢
    • 2013-05-30
    • 1970-01-01
    • 2020-10-08
    • 2015-04-07
    • 1970-01-01
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多