Hibernate 6 错误 InvalidDataAccessApiUsageException:非法 pop() 与不匹配的 JdbcValuesSourceProcessingState

问题描述 投票:0回答:3

在 Hibernate 6 中调用 JPA 方法时经常出现以下错误

org.springframework.dao.InvalidDataAccessApiUsageException: Illegal pop() with non-matching JdbcValuesSourceProcessingState
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:368)
java spring-boot hibernate spring-data-jpa hibernate-criteria
3个回答
3
投票

对于遇到此问题并使用 Quarkus 3 和 Vertx bare Api 的每个人。

我通过强制 JDBC 调用Vertx Eventbus线程来修复此错误,方法是将其包装在 EvenBus Consuming 函数中,如官方文档中所述,并摆弄@WithTransaction、@WithSession、@WithSessionOnDemand 或 Panache。 withTransaction{}.

这导致了我确信从长远来看会给我带来癌症的代码,作为业力和编码之神的报复。 但是,嘿,这是临时代码,因为我将我的 vertx 代码迁移到主要带有 vertx 火花的 quarkus。


    fun createToken(userId: String): Future<String> {
        val promise = Promise.promise<String>()
        eventBus.request<String>("createTokenMsg", userId)
            .onSuccess { msg -> promise.complete(msg.body()) }
            .onFailure(promise::fail)
        return promise.future()
    }

    @ConsumeEvent("createTokenMsg")
    fun createTokenMsgConsume(msg: Message<String>) {
        val userId = msg.body()

        createToken(userId).subscribe().with(
            { msg.reply(it.token) },
            { error: Throwable ->
                val txt = "Fail to create token for user id $userId"
                logger.log(Level.SEVERE, txt, error)
                msg.fail(500, txt)
            }
        )
    }

    @WithSession
    fun createToken(userId: String): Uni<TokenIdEntity> {
        return Panache
            .withTransaction { repository.findByUserId(userId) }
            .chain { found: TokenIdEntity? ->
            val token = found ?: TokenIdEntity(userId = userId)
            token.regenrateToken()

            Panache.withTransaction { repository.persistAndFlush(token) }
        }
    }

你可以将它与对象一起使用,但你讨厌使用 JsonObject

这不是一个理想的解决方案,因为:

  • 您滥用事件总线来进行函数调用(这会带来大量开销)
  • 如果您的代码在 vertx 集群中运行,它可能会被另一个实例消耗
  • 此时您丢失了堆栈跟踪,您可以记录 eventbus.request-Future 的 .onFailure 方法,但此时跟踪已丢失。 (这会耗费大量调试时间)

免责声明

我不是一个非常有经验的 Hibernate-Reactive、Panache 和 Quarkus 用户,所以也许这个解决方案是用猎枪射击一只麻雀,你错过了所有 7 轮,鸟就老死了,但它对我有用其他答案的描述性不够或不起作用。

@Transactional 解决方案对我不起作用,因为 quarkus 从 io 线程调用 JTA 事务时遇到问题

io.quarkus.runtime.BlockingOperationNotAllowedException: Cannot start a JTA transaction from the IO thread.

但是我对更好的解决方案感到好奇,并希望我的解决方案可能会引导一个更好的解决方案的方向。


1
投票

我们在项目中偶然发现了同样的问题,我们将具有 OneToMany 和 ManyToOne 关系的实体通过延迟加载传递给返回 CompletableFuture 的方法。作为一种解决方法,我们准备了 DTO,用于方法之外的进一步操作,传递它而不是实体对象,它就像一个魅力


0
投票

在我的系统中,Spring Boot 和 Hibernate 管理数据库。为了仍然可以访问实体管理器,我必须使用

@PersistenceContext(type = PersistenceContextType.TRANSACTION)
private final EntityManager entityManager;

这里重要的部分是

PersistenceContextType.TRANSACTION
,当我使用
PersistenceContextType.EXTENDED
时我得到了那个错误。特别是与其他交易有关。

因此,为了安全起见,我将

@Transactional(propagation = Propagation.REQUIRES_NEW)
添加到我的方法中。

现在我完全没有错误了。

© www.soinside.com 2019 - 2024. All rights reserved.