programing

스프링 데이터 jpa 쿼리에서 @lock timeout을 지정하는 방법은 무엇입니까?

powerit 2023. 6. 17. 09:44
반응형

스프링 데이터 jpa 쿼리에서 @lock timeout을 지정하는 방법은 무엇입니까?

을 지정하는 @Lock쿼리 시간 초과?저는 오라클 11g를 사용하고 있습니다. 저는 다음과 같은 것을 사용할 수 있기를 바랍니다.'select id from table where id = ?1 for update wait 5'.

나는 다음과 같이 방법을 정의했습니다.

@Lock(LockModeType.PESSIMISTIC_WRITE)
Stock findById(String id);

영원히 잠길 것 같아요.가 때할정설을 설정할 때.javax.persistence.lock.timeout=0LocalContainerEntityManagerFactoryBean.jpaProperties효과가 없습니다.

비관적으로 를 엔티를비관잠로잠그금모면드로 설정합니다.PESSIMISTIC_READ,PESSIMISTIC_WRITE또는PESSIMISTIC_FORCE_INCREMENT.

수 트랜잭션 경우, ,LockTimeoutException던져집니다.

비관적 잠금 시간 초과

지속성 제공자가 데이터베이스 테이블에 대한 잠금을 얻기 위해 기다려야 하는 시간(밀리초)은 javax.peristence.lock.timeout 속성을 사용하여 지정할 수 있습니다.자물쇠를 얻는 데 걸리는 시간이 이 재산의 값을 초과한다면,LockTimeoutException던지지만 현재 트랜잭션은 롤백으로 표시되지 않습니다.이 속성이 0으로 설정된 경우 지속성 공급자는 잠금을 즉시 가져올 수 없는 경우 를 던져야 합니다.

한다면javax.persistence.lock.timeout여러 위치에 설정된 경우 값은 다음 순서로 결정됩니다.

  1. 대주장한에나의 입니다.EntityManager또는Query methods.
  2. @NamedQuery주석
  3. 입니다.Persistence.createEntityManagerFactory방법.
  4. persistence.xml배포 설명자.

스프링 데이터 1.6 이상의 경우

@Lock는 Spring Data JPA 버전 1.6의 CRUD 방법에서 지원됩니다(사실 이미 마일스톤을 사용할 수 있습니다).자세한 내용은 이 티켓을 참조하십시오.

해당 버전에서는 다음을 선언하기만 하면 됩니다.

interface WidgetRepository extends Repository<Widget, Long> {

  @Lock(LockModeType.PESSIMISTIC_WRITE)
  Widget findOne(Long id);
}

구현 을 " " " " " " " " " " " " " " " " " " " 에 합니다.find(…)天皇를 EntityManager.

반면에,

Spring Data 1.6의 이전 버전의 경우

Data 인 기사@Lock주석은 사용자가 지적한 대로 쿼리에만 적용됩니다.전체 트랜잭션에 영향을 줄 수 있는 주석이 없습니다.을음생할수다있니를 만들 .findByOnePessimistic 부르는 findByOne인 잠금을 할 수 .findByOne항상 비관적인 잠금을 얻습니다.

독자적인 솔루션을 구현하고 싶다면 가능할 것입니다.에 후드아에래에▁under.@Lock은 다음과 같이 됩니다.LockModePopulatingMethodIntercceptor다음 작업을 수행합니다.

TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);

할 수 있습니다. 정적 잠금 관리자를 생성할 수 .ThreadLocal<LockMode>멤버 변수를 지정한 다음 스레드로컬에 설정된 잠금 모드로 bindResource라고 하는 모든 리포지토리의 모든 메서드를 둘러싸는 양상을 가집니다.이렇게 하면 스레드 단위로 잠금 모드를 설정할 수 있습니다.그런 다음 자신의 데이터를 생성할 수 있습니다.@MethodLockMode메서드를 실행하기 전에 스레드별 잠금 모드를 설정하고 메서드를 실행한 후에 삭제하는 측면으로 메서드를 래핑하는 주석입니다.

리소스 링크:

  1. 잠금 모드 유형을 활성화하는 방법.Spring Data JPA를 사용하여 엔티티를 조회할 때의 SEPMISTIC_WRITE?
  2. Spring Data JPA에 사용자 정의 방법을 추가하는 방법
  3. Postgres를 사용한 스프링 데이터 비관적 잠금 시간 초과
  4. JPA 쿼리 API

비관적 잠금 시간 초과의 다양한 예

비관적 잠금 설정

엔티티 개체는 잠금 방법으로 명시적으로 잠글 수 있습니다.

em.lock(employee, LockModeType.PESSIMISTIC_WRITE);

첫 번째 인수는 엔티티 개체입니다.두 번째 인수는 요청된 잠금 모드입니다.

A TransactionRequiredException명시적 잠금을 사용하려면 활성 트랜잭션이 필요하므로 잠금을 호출할 때 활성 트랜잭션이 없으면 느려집니다.

A LockTimeoutException요청된 비관적 잠금을 부여할 수 없는 경우 다음과 같이 느려집니다.

  • A PESSIMISTIC_READ 사용자인스턴스로 가 " " " (EntityManager " (EntityManager " (EntityManager " (EntityManager ") " " " 를 하고 있는 합니다.PESSIMISTIC_WRITE해당 데이터베이스 개체를 잠급니다.
  • A PESSIMISTIC_WRITE다른 사용자가 현재 다음 중 하나를 보유하고 있는 경우 잠금 요청이 실패합니다.PESSIMISTIC_WRITE자물쇠 또는PESSIMISTIC_READ해당 데이터베이스 개체를 잠급니다.

쿼리 힌트(범위) 설정

쿼리 힌트는 다음 범위(글로벌에서 로컬까지)에서 설정할 수 있습니다.

단위 - 전지성단대 - 합니다.persistence.xml속성:

<properties>
   <property name="javax.persistence.query.timeout" value="3000"/>
</properties>

- EntityManagerFactory - 사용 - 경createEntityManagerFacotory방법:

Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 4000);
EntityManagerFactory emf =
  Persistence.createEntityManagerFactory("pu", properties);

관리자의 - 엔터티 관리자 - 용사 - "createEntityManager방법:

Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 5000);
EntityManager em = emf.createEntityManager(properties);

또는 setProperty 메서드를 사용합니다.

em.setProperty("javax.persistence.query.timeout", 6000);

당분간named query- - 용사 hints요소:

@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c",
    hints={@QueryHint(name="javax.persistence.query.timeout", value="7000")})

- 를 합니다.setHint메서드(쿼리 실행 전):

query.setHint("javax.persistence.query.timeout", 8000);

리소스 링크:

  1. JPA의 잠금
  2. 비관적 잠금 시간 초과

스프링 데이터에서 사용할 수 있습니다.

@Lock(LockModeType.PESSIMISTIC_WRITE)
@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value ="5000")})
Stock findById(String id)

스프링 데이터 1.6 이상의 경우 스프링 데이터 jpa에서 제공하는 @Lock 주석을 사용할 수 있습니다.

또한 @QueryHints를 사용하여 제한 시간을 설정할 수도 있습니다.원래 기본 CRUD 메서드에서는 쿼리 힌트 주석을 지원하지 않았지만 수정 1.6M1 이후에 사용할 수 있습니다. https://jira.spring.io/browse/DATAJPA-173

아래는 배타적 잠금인 SEPICISTIC_WRITE 모드 유형의 SEPICATIC Lock의 예입니다.

@Lock(LockModeType.PESSIMISTIC_WRITE) 
@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value   ="5000")}) 
Customer findByCustomerId(Long customerId);

javax.componence.lock.dll은 아래와 같이 제공될 때에도 나에게 작동하지 않는 것 같습니다.

@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout",value = "15000")})

하지만 저는 효과가 있는 다른 것을 시도했습니다.@Repository와 CrudRepository를 사용하는 대신 엔티티 관리자를 사용하여 hbernate를 구성합니다.사용된 생성잠금 및 잠금 시간 제한 설정과 함께 쿼리합니다.그리고 이 구성은 예상대로 작동합니다.병렬로 실행 중인 두 개의 트랜잭션이 있으며 DB에서 정확히 같은 행을 잠그려고 합니다.첫 번째 트랜잭션은 WRITE 잠금을 획득할 수 있으며 잠금을 해제하기 전에 약 10초 동안 잠금을 유지합니다.한편, 두 번째 트랜잭션은 동일한 행에서 잠금을 획득하려고 하지만 javax.persistence.lock.timeout이 15초로 설정되어 있기 때문에 잠금이 해제될 때까지 기다렸다가 자체 잠금을 획득합니다.따라서 흐름을 직렬화합니다.

@Component
public class Repository {

    @PersistenceContext
    private EntityManager em;

    public Optional<Cache> getById(int id){
        List<Cache> list = em.createQuery("select c from Cache c where c.id = ?1")
                            .setParameter(1, id)
                            .setHint("javax.persistence.lock.timeout", 15000)
                            .setLockMode(LockModeType.PESSIMISTIC_WRITE)
                            .getResultList();

    
        return Optional.ofNullable(list.get(0));
    }
    
    public void save(Cache cache) {
        cache = em.find(Cache.class, cache.getId());
        em.merge(cache);
    }
}

불하게도행,,javax.persistence.lock.timeout속성은 봄 데이터 jpa의 오라클 제공자만 지원합니다.적절한 잠금 시간 제한을 설정하려면 각 DBMS 공급자에 대해 일부 사용자 지정 기본 SQL 문을 실행해야 합니다.

다음은 잠금 시간 제한을 3초로 설정하는 DBMS 관련 명령문입니다.

MySQL

set session innodb_lock_wait_timeout = 3

PostgreSQl

set local lock_timeout = 3000

SQL Server

set lock_timeout 3000

이 주제에 대한 자세한 내용은 다음 게시물을 참조하십시오. https://blog.mimacom.com/handling-pessimistic-locking-jpa-oracle-mysql-postgresql-derbi-h2/

언급URL : https://stackoverflow.com/questions/29765934/how-to-specify-lock-timeout-in-spring-data-jpa-query

반응형