Исключение режима 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;
  }
}
Другие вопросы по тегам