오래된 값을 사용하는 트랜잭션 내에서 실행되는 스프링 네이티브 쿼리
Spring Boot(1.4.4)를 사용하고 있습니다.REALEASE)를 사용하여 MySql 데이터베이스를 관리합니다.다음과 같은 사건을 맡았습니다.
- 다음을 사용하여 하나의 장비에서 수행된 하나의 개정판을 업데이트합니다.
RevisionService
. RevisionService
하고 "" " " " 를 합니다.EquipmentService
장비 상태를 업데이트합니다.- updateEquipmentStatus는 DB 저장 프로시저를 호출하여 해당 리비전과 함께 장비를 평가하고 필드를 업데이트합니다.
몇 가지 옵션을 시도했지만 장비에 대한 업데이트된 상태를 얻지 못했습니다.updateEquipmentStatus
메소드는 장비에 대한 이전 상태를 계속 기록합니다(트랜잭션에 저장 중인 현재 리비전은 고려하지 않음).코드는 다음과 같이 작성됩니다.
개정 서비스
@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);
}
}
장비 서비스
@Service
public class EquipmentService{
@org.springframework.transaction.annotation.Transactional
public Long updateEquipmentStatus(Long idEquipment){
repo.updateEquipmentStatus(idEquipment);
}
}
장비 보고서
@Repository
public interface EquipmentRepo extends CrudRepository<Equipment, Long> {
@Modifying
@Procedure(name = "pupdate_equipment_status")
void updateEquipmentStatus(@Param("id_param") Long idEquipment);
}
모두알고 , 제 이 해 하 스 모 거 프 주 의 달 때 이 문 에 렸 기 석 에 래 링 가 두 기 법 두 방 로 는 ▁as 때 , 에 문 ▁are ▁as ▁methods ▁the ▁with 제updateEquipmentStatus
메서드는 현재 트랜잭션의 범위에서 실행되어야 합니다.저는 또한 다양한 옵션을 사용하여 시도했습니다.@Transactional
의 주석updateEquipmentStatus
를 들어, 를들어예와 같은@Transactional(isolation=Isolation.READ_UNCOMMITTED)
.) 및 (같은트랜션사있필때않지요습하다니문에기용고을하잭)▁(않다습니▁(같▁shouldn)@Transactional(propagation=Propagation.REQUIRES_NEW)
하지만 계속해서 현재 상태를 고려하지 않고 있습니다. DB MySql DB에 됩니다.
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는 모든 테이블에 사용되는 엔진입니다.
갱신하다
nativeQuery를 대신 사용하도록 repo 방법을 변경했는데 동일한 문제가 계속 발생하므로 관련된 DB 절차를 폐기해야 합니다.
@Modifying
@Query(nativeQuery = true, value= "update tequipment set equipment_status = (CASE WHEN (...))")
void updateEquipmentStatus(@Param("id_param") Long idEquipment);
업데이트 2
더 많은 테스트를 수행하고 방법 내에 로그를 추가한 것이 구체적인 문제입니다.
- 장비 서비스에서 수행된 변경 사항은 업데이트 기능에 의해 적절히 선택됩니다(장비가 변경되면 상태 장비가 올바르게 계산됨).
- 리비전 서비스(리비전)에서 변경하면 오래된 값 장비가 됩니다(스프링이 REQUESTES_NEW를 사용하여 다른 트랜잭션에서 이를 수행하는지 여부는 중요하지 않습니다).은 REQUESTS_NEW에서 할 때 하는 것 .
establishEquipmentStatus
현재 트랜잭션 이름은 변경되지만 네이티브 쿼리에 최신 값이 없기 때문입니다(커밋되지 않은 트랜잭션 때문에?).제거도 시도했습니다.@Transactional
부터establishEquipmentStatus
동일한 거래가 사용되지만 문제가 계속 발생합니다. - 장비 상태를 업데이트하는 데 사용되는 쿼리에는 trevision을 사용하는 여러 하위 쿼리가 포함된 사례 표현식이 있음을 강조하고 싶습니다.
다음 코드를 추가하면 수정됩니다(데이터베이스로 트랜잭션 상태를 프로그래밍 방식으로 플러시).
@Service
public class EquipmentService{
@PersistenceContext
private EntityManager entityManager;
@org.springframework.transaction.annotation.Transactional
public Long updateEquipmentStatus(Long idEquipment){
entityManager.flush();
repo.updateEquipmentStatus(idEquipment);
}
}
그래도 선언적인 방법을 찾는 것은 좋을 것입니다.
읽기를 커밋되지 않음으로 변경하는 것은 올바른 생각이지만 저장 프로시저를 호출하기 전에 엔티티 관리자를 플러시해야 합니다.다음 스레드 참조:
저장 프로시저의 쿼리에 스프링 트랜잭션을 인식시키는 방법은 무엇입니까?
개인적으로 당신이 저장 프로시저를 사용하도록 절대적으로 강요하지 않는 한 저는 봄에 모든 것을 할 것입니다.
언급URL : https://stackoverflow.com/questions/42294469/spring-native-query-executed-within-a-transaction-taking-outdated-value
'programing' 카테고리의 다른 글
java.sql.SQLException 매개 변수 인덱스가 범위를 벗어남(1 > 매개 변수 수, 즉 0) (0) | 2023.07.26 |
---|---|
데이터베이스 열의 비트 플래그에 대한 단점은 무엇입니까? (0) | 2023.07.21 |
Oracle 11g은 정규식으로 일치하는 모든 항목을 가져옵니다. (0) | 2023.07.21 |
봄 구름과 유레카가 있는 리본: java.lang.잘못된 상태 예외:Samarths-MacBook-Pro.local에 사용할 수 있는 인스턴스가 없습니다. (0) | 2023.07.21 |
Panda DataFrame에 메타 정보/메타데이터 추가 (0) | 2023.07.21 |