Исключение режима Hibernate Reative Query Lock
При использовании Panache-reactive с smallrye-reactive-messaging в quarkus возникает много проблем с тайм-аутом/сеансом. Небольшой вариант проблемы с тайм-аутом наблюдается при использовании PanacheRepository.
Основываясь на знаниях Panache reactiveTransactional timeout без трассировки стека , я использовал непосредственно фабрику сеансов, создал Mutiny.Session и запустил свой запрос, и по большей части он будет работать, за исключением случаев, когда я пытаюсь добавитьsetLockMode(LockMode.OPTIMISTIC_FORCE_INCREMENT)
так как это вызовет
Caused by: java.lang.UnsupportedOperationException
at org.hibernate.reactive.event.impl.DefaultReactiveLockEventListener.onLock(DefaultReactiveLockEventListener.java:240)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
at org.hibernate.internal.SessionImpl.fireLock(SessionImpl.java:727)
at org.hibernate.internal.SessionImpl.fireLock(SessionImpl.java:717)
at org.hibernate.internal.SessionImpl.access$1000(SessionImpl.java:202)
at org.hibernate.internal.SessionImpl$LockRequestImpl.lock(SessionImpl.java:2656)
at org.hibernate.loader.custom.CustomLoader$1.afterLoad(CustomLoader.java:362)
at org.hibernate.reactive.loader.ReactiveLoaderBasedResultSetProcessor.lambda$reactiveInitializeEntitiesAndCollections$3(ReactiveLoaderBasedResultSetProcessor.java:188)
at java.base/java.util.concurrent.CompletableFuture.uniAcceptNow(CompletableFuture.java:757)
at java.base/java.util.concurrent.CompletableFuture.uniAcceptStage(CompletableFuture.java:735)
at java.base/java.util.concurrent.CompletableFuture.thenAccept(CompletableFuture.java:2182)
at java.base/java.util.concurrent.CompletableFuture.thenAccept(CompletableFuture.java:144)
at org.hibernate.reactive.loader.ReactiveLoaderBasedResultSetProcessor.reactiveInitializeEntitiesAndCollections(ReactiveLoaderBasedResultSesor.java:150)
at org.hibernate.reactive.loader.ReactiveLoaderBasedResultSetProcessor.reactiveExtractResults(ReactiveLoaderBasedResultSetProcessor.java:83)
at org.hibernate.reactive.loader.ReactiveLoader.reactiveProcessResultSet(ReactiveLoader.java:145)
at org.hibernate.reactive.loader.ReactiveLoader.lambda$doReactiveQueryAndInitializeNonLazyCollections$0(ReactiveLoader.java:77)
at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1150)
... 63 more
В идеале он должен иметьDefaultReactiveLockEventListener.reativeOnLock
но из трассировки стека он перешел кDefaultReactiveLockEventListener.OnLock
Это моя полная реализация.
return sessionfactory.withTransaction((session, tx) -> {
return session.createNativeQuery("select * from model", Model.class)
.setLockMode(LockMode.OPTIMISTIC_FORCE_INCREMENT).getResultList().onItemOrFailure()
.transform((existingModels, t) -> {
if (t != null) {
Log.error(t, t);
}
List<Model> toSave = Lists.newArrayList();
for (Model publish : publishedModels) {
boolean exist = false;
for (Model existing : existingModels) {
if (publish.getName().equals(existing.getName()) {
toSave.add(existing);
exist = true;
}
}
if (!exist) {
publish.setId(UUID.randomUUID());
publish.setRevision(1L);
toSave.add(publish);
}
}
Wrap wrap = new Wrap();
wrap.setSession(session);
wrap.setModels(toSave);
return wrap;
}).chain(wrap -> {
return wrap.getSession().persistAll(wrap.getModels().toArray()).invoke(v -> session.flush());
});
});
Это ошибка или что-то, что я могу улучшить в своем коде, чтобы обойти это? Мне нужна была блокировка, чтобы убедиться, что нет двух транзакций, которые будут обновлять одну и ту же версию (с использованием JPA @Version) записи.
1 ответ
Этот следующий код, похоже, работает, но я не уверен, что это правильный путь.
for (Model existing : existingModels) {
if (publish.getName().equals(existing.getName()) {
toSave.add(existing);
session.lock(existing, LockMode.PESSIMISTIC_FORCE_INCREMENT);
exist = true;
}
}