Вставьте строку, если условие запроса соответствует JPA и пружине - PullRequest
0 голосов
/ 18 января 2019

Я думаю, что этот вопрос похож на Пессимистические блокировки базы данных с данными Spring JPA (Hibernate под капотом) , но я подумал, что я бы спросил отдельно, как не совсем то же самое.

У меня есть многопоточное / узловое приложение Springboot поверх базы данных mariadb с таблицей типа

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

Иметь класс домена Job, как и следовало ожидать.

Иметь интерфейс JobRepository, который расширяет CrudRepository<Job,Integer> и класс обслуживания.

Правило применения: мы не можем вставить новое задание, если у него один и тот же владелец и набор значений состояния. например Если бы это была старая школа, я бы просто:

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.

Я разделился на операции с БД. Определен метод хранилища:

@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;
    }
}

Но при этом я не получаю желаемого эффекта.

LockModeType READ и WRITE позволяет создавать дубликаты.

LockModeType для PESSIMISTIC_READ и PESSIMISTIC_WRITE может привести к ошибкам взаимоблокировки.

Так что, думаю, мне нужен один из двух вариантов:

  • Есть ли способ заставить получить INSERT...SELECT WHERE NOT EXISTS в метод JPA / CrudRepository?
  • Есть ли способ получить услугу? метод, чтобы эффективно обернуть проверку счета и вставку в том же блокировка?

Если нет способа сделать это, я думаю, я попытаюсь получить доступ к базовому jdbc-соединению и explicity, запустив оператор LOCK TABLE (или вставку ... select, но идея мне не нравится из-за того, что держать его как JPA, вероятно, лучше).

Надеюсь, я все правильно объяснил. Заранее спасибо за помощь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...