在 Hibernate 6 中调用 JPA 方法时经常出现以下错误
org.springframework.dao.InvalidDataAccessApiUsageException: Illegal pop() with non-matching JdbcValuesSourceProcessingState
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:368)
对于遇到此问题并使用 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
这不是一个理想的解决方案,因为:
免责声明
我不是一个非常有经验的 Hibernate-Reactive、Panache 和 Quarkus 用户,所以也许这个解决方案是用猎枪射击一只麻雀,你错过了所有 7 轮,鸟就老死了,但它对我有用其他答案的描述性不够或不起作用。
@Transactional 解决方案对我不起作用,因为 quarkus 从 io 线程调用 JTA 事务时遇到问题
io.quarkus.runtime.BlockingOperationNotAllowedException: Cannot start a JTA transaction from the IO thread.
但是我对更好的解决方案感到好奇,并希望我的解决方案可能会引导一个更好的解决方案的方向。
我们在项目中偶然发现了同样的问题,我们将具有 OneToMany 和 ManyToOne 关系的实体通过延迟加载传递给返回 CompletableFuture 的方法。作为一种解决方法,我们准备了 DTO,用于方法之外的进一步操作,传递它而不是实体对象,它就像一个魅力
在我的系统中,Spring Boot 和 Hibernate 管理数据库。为了仍然可以访问实体管理器,我必须使用
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
private final EntityManager entityManager;
这里重要的部分是
PersistenceContextType.TRANSACTION
,当我使用PersistenceContextType.EXTENDED
时我得到了那个错误。特别是与其他交易有关。
因此,为了安全起见,我将
@Transactional(propagation = Propagation.REQUIRES_NEW)
添加到我的方法中。
现在我完全没有错误了。