spring - Spring TransactionManager 行为与 Spring Data 和 JpaRepository
问题描述
我有一个控制器,它执行以下操作
- 一个提交端点,它在数据库中保存一个条目,然后异步调用一些外部服务
- 通过观察db来跟踪异步调用的更新(这个调用更新一个关联的表)并更新在第一步中创建的条目的状态
我正在使用@Query Annotation 来验证 db 中是否存在第一步条目,并且它总是返回空。我尝试将其更改为默认的 spring 方法并开始返回插入的值。
我阅读了有关代理、@Transactional 以及 JPARepository 中的非 CRUD 方法如何是非事务性的,并尝试了一些事情,例如事务传播和自我注入,甚至明确标记了 repo 方法 @Transactional。但他们都没有解决这个问题。使用弹簧数据方法解决了它,但我仍然不明白发生了什么。有人可以帮助解释这种行为。
基本代码片段如下
我的控制器
@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);
}
推荐阅读
- java - 从 json 发布请求中检索 Java 对象
- java - 收集地图
从地图流 > - python - 使用 IIS 显示 Bokeh 仪表板
- python - CSV 文件到 JSON 用于使用 python 的嵌套数组通用模板(用于 csv 到 mongodb 插入)
- mysql - 在mysql中查找行的位置
- redirect - 在 url #?ref=abandmail5 中使用参数时,Elementor 表单在提交后不会重定向
- java - 当我的共享变量可以随时更改时,如何使我的代码线程安全?
- ansible - ansible将多个变量输出到同一行
- c# - 无法将文件写入 Directory.GetCurrentDirectory() 中的路径
- asp.net - 常规路由中如何设置Route Prefix