爲了管理MySql數據庫,我使用Spring Boot(1.4.4.REALEASE)和Spring Data。我有以下情況:在一個事務中執行的Spring本地查詢取得了過時的值
- 我們更新了使用
RevisionService
在一臺設備上執行的一個修訂。 RevisionService
保存修訂並調用EquipmentService
來更新設備狀態。- updateEquipmentStatus會對Db存儲過程進行調用,以便完全評估設備及其修訂版並更新字段。
我試過一些選項,但沒有達到獲取設備的更新狀態。 updateEquipmentStatus
方法不斷寫入設備的先前狀態(不考慮當前修訂存儲在事務中)。該代碼是這樣寫的:
RevisionService
@Service
public class RevisionService{
@org.springframework.transaction.annotation.Transactional
public Long saveRevision(Revision rev){
//save the revision using JPA-Hibernate
repo.save(rev);
equipmentService.updateEquipmentStatus(idEquipment);
}
}
EquipmentService
@Service
public class EquipmentService{
@org.springframework.transaction.annotation.Transactional
public Long updateEquipmentStatus(Long idEquipment){
repo.updateEquipmentStatus(idEquipment);
}
}
EquipmentRepo
@Repository
public interface EquipmentRepo extends CrudRepository<Equipment, Long> {
@Modifying
@Procedure(name = "pupdate_equipment_status")
void updateEquipmentStatus(@Param("id_param") Long idEquipment);
}
據我所知,由於這兩種方法都使用Spring的事務註釋,所以updateEquipmentStatus
方法應該在當前事務的範圍內執行。我還嘗試使用的@Transactional
註釋的不同選項,例如@Transactional(isolation=Isolation.READ_UNCOMMITTED)
(這不應該是必需的,因爲我使用相同的事務)和@Transactional(propagation=Propagation.REQUIRES_NEW)
,但不會考慮當前狀態。這是我的存儲過程是如何保存到MySQL數據庫:
CREATE DEFINER=`root`@`localhost` PROCEDURE `pupdate_equipment_status`(IN `id_param` INT)
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
COMMENT ''
BEGIN
/*Performs the update considering tequipment and trevision*/
/*to calculate the equipment status, no transaction is managed here*/
END
我也想澄清的是,如果我執行在設備本身(這隻會影響精裝配件)做一些修改,狀態得到了適當的更新。 InnoDb是用於所有表格的引擎。
UPDATE
只是改變了回購方式使用nativeQuery來代替,而同樣的問題持續發生,所以數據庫程序參與應該被丟棄:
@Modifying
@Query(nativeQuery = true, value= "update tequipment set equipment_status = (CASE WHEN (...))")
void updateEquipmentStatus(@Param("id_param") Long idEquipment);
UPDATE2
已經完成更多的測試,並增加了日誌與方法TransactionSynchronizationManager.getCurrentTransactionName()
,這就是具體問題:
- 變化的設備服務進行適當的更新功能(採摘當東西精裝配件的變化,在狀態精確計算配件)。
- 修改服務(trevision)中所做的更改會導致tequipment中的過期值(如果Spring使用REQUIRES_NEW在不同的事務中執行此操作,則無關緊要)。當在
establishEquipmentStatus
中使用REQUIRES_NEW時,Spring似乎會正確創建一個新的事務,因爲當前事務名稱發生更改,但本機查詢沒有最新值(因爲事務沒有被提交之前?)。還嘗試從establishEquipmentStatus
中刪除@Transactional
,以便使用相同的事務,但問題不斷髮生。 - 我想突出顯示查詢用於更新設備狀態具有case expression與多個子查詢使用trevision。
嗨,對不起延時。實際上,問題不是存儲過程特定的,但似乎它涉及許多涉及同一事務的表(它需要舊錶值)。或多或少,這就是執行流程:1.使用Hibernate更新修訂版。 2.執行'updateEquipmentStatus'方法,該方法觸發修改的本地查詢(此查詢使用了一些涉及步驟1的數據,這些數據已過時)。 –