Я думаю, что этот вопрос похож на Пессимистические блокировки базы данных с данными 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, вероятно, лучше).
Надеюсь, я все правильно объяснил. Заранее спасибо за помощь.