Spring TransactionManager 行为与 Spring 数据和 JpaRepository

Spring TransactionManager behavior with Spring Data and JpaRepository

我有一个控制器可以执行以下操作

  1. 一个提交端点,它在数据库中保存一个条目,然后异步调用一些外部服务
  2. 通过观察数据库跟踪异步调用的更新(此调用更新关联的 table)并更新在第一步中创建的条目的状态

我正在使用@Query 注释来验证数据库中是否存在第一步条目并且它总是返回空。我尝试将其更改为默认的 spring 方法,它开始返回插入的值。

我了解了代理、@Transactional 以及 JPARepository 中的非 CRUD 方法是非事务性的,并尝试了一些事情,例如事务传播和自我注入,甚至显式标记回购方法 @Transactional。但是 none 解决了这个问题。使用 spring 数据方法解决了它,但我仍然不明白发生了什么。谁能帮忙解释一下这种行为。

基本代码片段如下

我的控制器

@RestController
public class MyController {

    private final MyService myService;
    private final MyRepository myRepository;


    @Autowired
    public MyController(MyService myService,
                        MyRepository myRepository) {
        this.myService = myService;
        this.myRepository = myRepository;
    }

    @PostMapping(value = "/submit")
    public ResponseEntity<MyResponse> submit(@Valid @RequestBody MyRequest myRequest) {
        return ResponseEntity
                .accepted()
                .body(MyResponse.success(myService.submit(myRequest), "SUBMITTED"));
    }

    /**
     * This method is to update the status of the entry created by /submit endpoint
     * if the asynchoronous process triggered by submit endpoint update an associated table
     */
    @PostConstruct
    private void trackUpdates() {
        ..
        someObserver.subscribe(trackedAssociatedEntity -> {
            myService.trackAndUpdateBasedOnAssociatedEntity(trackedAssociatedEntity);
        });
    }

}

我的服务

@Service
@Transactional
public class MyService {


    private final MyRepository myRepository;


    @Autowired
    public MyService(MyRepository myRepository) {
        this.myRepository = myRepository;
    }


     submit(MyRequest myRequest) {
         myRepository.save(myEntity);
         //makes that asynchronous call
    }
    public void trackAndUpdateBasedOnAssociatedEntity(@NotNull MyAssociatedEntity myassociatedEntity) {
        //  This commented call always return empty but the uncommented code works as expected
        //        List<MyEntity> existingEntity =
        //                myRepository.findEntityByField1AndField2(myassociatedEntity.getField1(),myassociatedEntity.getField2());

        List<MyEntity> existingEntities =
                        myRepository.findByField1AndField2(myassociatedEntity.getField1(),myassociatedEntity.getField2());

        if(existingEntities.isEmpty()){
                    //create new
                }else{
                    //update
                }
            }
        }
    }
}

我的存储库

@Repository
public interface MyRepository extends JpaRepository<MyEntity, Long> {

    @Query("SELECT e FROM MyEntity e WHERE e.field1 = ':field1' and e.field2 = ':field2' ")
    List<MyEntity> findEntityByField1AndField2(String field1, String field2);

    List<MyEntity> findByField1AndField2(String field1, String field2);
}

我认为 '' 不需要。请尝试以下操作:

@Repository
public interface MyRepository extends JpaRepository<MyEntity, Long> {

    @Query("SELECT e FROM MyEntity e WHERE e.field1 = :field1 and e.field2 = :field2")
    List<MyEntity> findEntityByField1AndField2(String field1, String field2);

    List<MyEntity> findByField1AndField2(String field1, String field2);
}