Spring TransactionManager 行为与 Spring 数据和 JpaRepository
Spring TransactionManager behavior with Spring Data and JpaRepository
我有一个控制器可以执行以下操作
- 一个提交端点,它在数据库中保存一个条目,然后异步调用一些外部服务
- 通过观察数据库跟踪异步调用的更新(此调用更新关联的 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);
}
我有一个控制器可以执行以下操作
- 一个提交端点,它在数据库中保存一个条目,然后异步调用一些外部服务
- 通过观察数据库跟踪异步调用的更新(此调用更新关联的 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);
}