[java] Java-JPA-@Version 주석

@VersionJPA에서 주석은 어떻게 작동합니까?

다음과 같은 다양한 답변을 찾았습니다.

JPA는 항목의 버전 필드를 사용하여 동일한 데이터 저장소 레코드에 대한 동시 수정을 감지합니다. JPA 런타임이 동일한 레코드를 동시에 수정하려는 시도를 감지하면 마지막 커밋을 시도하는 트랜잭션에 예외가 발생합니다.

그러나 나는 그것이 어떻게 작동하는지 여전히 잘 모르겠습니다.


또한 다음 줄에서와 같이 :

버전 필드를 변경할 수없는 것으로 간주해야합니다. 필드 값을 변경하면 결과가 정의되지 않습니다.

버전 필드를 다음과 같이 선언해야 함을 의미합니까 final?



답변

하지만 여전히 어떻게 작동하는지 잘 모르겠습니까?

엔티티 MyEntity에 주석이 달린 version속성 이 있다고 가정 해 보겠습니다 .

@Entity
public class MyEntity implements Serializable {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @Version
    private Long version;

    //...
}

업데이트시 다음과 같이 주석이 추가 된 필드 @Version가 증분되고 WHERE절에 추가됩니다 .

UPDATE MYENTITY SET ..., VERSION = VERSION + 1 WHERE ((ID = ?) AND (VERSION = ?))

WHERE절이 레코드와 일치하지 않으면 (동일한 엔터티가 이미 다른 스레드에 의해 업데이트 되었기 때문에) 지속성 공급자가 OptimisticLockException.

버전 필드를 최종적으로 선언해야 함을 의미합니까?

아니요.하지만 호출해서는 안되는 세터를 보호하는 것을 고려할 수 있습니다.


답변

@Pascal 답변은 완벽하게 유효하지만 내 경험상 아래 코드가 낙관적 잠금을 달성하는 데 도움이된다는 것을 알았습니다.

@Entity
public class MyEntity implements Serializable {
    // ...

    @Version
    @Column(name = "optlock", columnDefinition = "integer DEFAULT 0", nullable = false)
    private long version = 0L;

    // ...
}

왜? 때문에:

  1. 로 주석이 달린 필드 가 실수로로 설정된 경우 낙관적 잠금 이 작동하지 않습니다 .@Versionnull
  2. 이 특별한 필드가 반드시 오해의 소지를 피하기 위해 객체의 비즈니스 버전, 아니므로, 내가 좋아하는 뭔가 같은 필드 이름을 선호 optlock하기보다는 version.

첫 번째 요점은 JPA 공급 업체가 생성시 필드에 적용 하기 때문에 데이터베이스에 데이터를 삽입하는 데 JPA 사용하는 경우에는 중요하지 않습니다 . 그러나 거의 항상 일반 SQL 문도 사용됩니다 (적어도 단위 및 통합 테스트 중).0@version


답변

데이터베이스에서 엔티티가 업데이트 될 때마다 버전 필드가 1 씩 증가합니다. 데이터베이스의 엔터티를 업데이트하는 모든 작업이 WHERE version = VERSION_THAT_WAS_LOADED_FROM_DATABASE쿼리에 추가 됩니다.

작업의 영향을받는 행을 확인할 때 jpa 프레임 워크는로드와 지속 사이에 버전 번호가 증가하면 쿼리가 데이터베이스에서 엔티티를 찾지 못하기 때문에 엔티티를로드하고 유지하는 사이에 동시 수정이 없는지 확인할 수 있습니다.


답변

한 번에 하나의 업데이트 만 보장하는 데 사용되는 버전입니다. JPA 공급자는 버전을 확인합니다. 예상 버전이 이미 증가하면 다른 사람이 이미 엔티티를 업데이트하므로 예외가 발생합니다.

따라서 엔티티 값을 업데이트하는 것이 더 안전하고 낙관적입니다.

값이 자주 변경되는 경우 버전 필드를 사용하지 않는 것이 좋습니다. 예를 들어 “카운터 필드가있는 엔티티, 웹 페이지에 액세스 할 때마다 증가합니다”


답변

정보를 조금 더 추가하세요.

JPA는 내부적으로 버전을 관리하지만을 통해 레코드를 업데이트 할 때는 그렇게하지 않습니다.이 JPAUpdateClause경우 쿼리에 버전 증분을 수동으로 추가해야합니다.

JPQL을 통한 업데이트에 대해서도 마찬가지입니다. 즉, 엔티티에 대한 단순한 변경이 아니라 최대 절전 모드에서 수행하더라도 데이터베이스에 대한 업데이트 명령입니다.

페드로


답변