我有以下示例代碼:
@Transactional
public void someMethod() {
MyEntity myEntity = myRepo.findById(1).orElse(null);
if (myEntity != null) {
myEntity.setValue("something");
myRepo.save(myEntity);
}
}
并且myRepo是一個實體:
public interface MyRepo extends CrudRepository<MyEntity, Integer> {}
所以我可以看到第一個 SELECT 來自myRepo.findById(1),這是有道理的。但是當代碼運行到 時myRepo.save(myEntity),Hibernate 以某種方式認為myEntity回傳的 fromfindById()不是托管的,因此它再次執行另一個 SELECT 以創建托管物體,然后使用 替換其值myEntity,然后執行 UPDATE。
您能否解釋一下為什么需要另一個 SELECT 以及如何避免它?此外,@Transactional無論有沒有它,方法上方的注釋都不會改變這種行為。
uj5u.com熱心網友回復:
它來自 Spring 中不太明確的行為@Transactional。@Transactional意味著兩件事:
- 打開的持久背景關系(休眠會話)
- 交易本身。
您有第二個選擇,因為在您的情況下@Transactional根本不起作用。Hibernate 為每個呼叫打開一個新的持久背景關系
myRepo.findById(1)myRepo.save(myEntity)
如果要進行自呼叫,則需要將對服務的參考傳遞給呼叫事務方法的方法。
class SomeServiceImpl implements SomeService {
public void doWork(SomeService self) {
self.someMethod();
}
@Transactional
public void someMethod() {
MyEntity myEntity = myRepo.findById(1).orElse(null);
if (myEntity != null) {
myEntity.setValue("something");
myRepo.save(myEntity);
}
}
}
另一種方法是自動軟體self到服務領域。但這不是很好,因為您必須通過歸檔注入來使用自動軟體。使用建構式來實作自動化是不可能的。所以很難對服務進行單元測驗。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/421019.html
標籤:
