programing

쿼리 조건이 JPA 및 스프링을 충족하는 경우 행 삽입

newsource 2023. 1. 20. 16:13

쿼리 조건이 JPA 및 스프링을 충족하는 경우 행 삽입

Spring data JPA(Hibernate under the hood)에 의한 Database의 비관적인 locks와 비슷하다고 생각합니다만, 꼭 같은 것은 아니기 때문에 별도로 묻고 싶다고 생각했습니다.

mariadb 데이터베이스 위에 멀티 스레드/노드 스프링 부트 애플리케이션이 있으며 다음과 같은 테이블이 있습니다.

CREATE TABLE job (
id      INT PRIMARY KEY AUTO_INCREMENT,
owner   VARCHAR(50),
status  VARCHAR(10) );

한 잔 하다Job예상대로 도메인 클래스입니다.

한 잔 하다JobRepository확장 인터페이스CrudRepository<Job,Integer>서비스 클래스도 있습니다.

응용 프로그램 규칙은 소유자 및 상태 값 집합이 동일한 경우 새 작업을 삽입할 수 없다는 것입니다. 예를 들어 이전 학교 네이티브 SQL인 경우 다음을 수행합니다.

START TRANSACTION;
INSERT INTO job (owner, status)
SELECT 'fred', 'init' FROM DUAL
WHERE NOT EXISTS
(   SELECT 1 FROM job
    WHERE owner = 'fred' AND status IN ('init', 'running')
);
COMMIT;

JPA/CrudRepository에서 이 작업을 수행하는 방법

나는 DB 업무로 나누었다.저장소 메서드를 정의했습니다.

@Lock(LockModeType.READ)
long countByOwnerAndStatusIn(String owner, List<String> status);

그리고 다음과 같은 서비스 방법을 사용했습니다.

@Transactional
public Job createJob(Job job) {
    if (jobRepository.countByOwnerAndStatusIn(job.getOwner(), Job.PROGRESS_STATUS) == 0) {
        // Sleeps just to ensure conflicts
        Thread.sleep(1000);
        Job newJob = jobRepository.save(job);
        Thread.sleep(1000);
        return newJob
    }
    else {
        return null;
    }
}

하지만 이것으로 나는 원하는 효과를 얻지 못한다.

READ 및 WRITE의 LockModeType을 사용하면 중복을 생성할 수 있습니다.

PEASMISTIC_READ 및 PEASMISTIC_WRITE의 LockModeType을 사용하면 교착 오류가 발생할 수 있습니다.

다음 두 가지 방법 중 하나를 찾아야 할 것 같습니다.

  • 이 모든 것을 얻을 수 있는 방법은 없을까?INSERT...SELECT WHERE NOT EXISTSJPA/CrudRepository 메서드로 변경하시겠습니까?
  • 카운트 체크와 인서트를 같은 잠금으로 효과적으로 랩할 수 있는 방법이 있습니까?

둘 다 할 방법이 없는 경우 기본 jdbc 접속에 접속하여 다음 명령을 실행합니다.LOCK TABLE스테이트먼트(또는 삽입...)선택하지만, JPA를 그대로 두는 것이 좋다고는 생각하지 않습니다).

내가 제대로 설명했길 바란다.잘 부탁드립니다.

언급URL : https://stackoverflow.com/questions/54246960/insert-row-if-query-condition-met-jpa-and-spring