You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同一事务中基于其他更新实体持久化新实体的正确方式

问题:Wildfly Web应用中同一JTA事务内基于更新实体持久化JPA实体

需求描述

在Wildfly Web应用中,需要在同一JTA事务内,基于当前正在更新的实体来持久化新的JPA实体。具体来说:当EntityManager更新某类实体时,要基于该实体类型执行自定义JPQL查询,找出需要在同一事务中额外持久化到数据库的记录。

已尝试方案

方案一

使用javax.persistence事件(如@PreUpdate事件)收集所有关注的更新实体。由于javax.persistence事件不允许直接使用EntityManager或Query对象,我将这些实体存储在TransactionScoped bean的一个映射中,随后通过CDI事件监听事务完成前阶段:

void beforeTransactionCommit(@Observes(during = TransactionPhase.BEFORE_COMPLETION) @Initialized(TransactionScoped.class) final Object ignored){
    // 找出需要持久化的记录并通过EntityManager持久化
}

基于存储的更新实体找出所有需要持久化的记录,并在当前事务中持久化它们。

这种方法大多有效,但有时javax.persistence事件会在指定的CDI事件之后触发,导致无法及时注册更新的实体。

方案二

仍然使用javax.persistence事件,但不再通过CDI事件监听事务完成前阶段,而是使用事务Synchronization,通过TransactionSynchronizationRegistry.registerInterposedSynchronization进行注册。在Synchronization.beforeCompletion()方法中,找出所有需要创建的记录,通过EntityManager持久化后手动执行刷新(因为EntityManager的托管刷新已在同步调用前完成):

@Override
public void beforeCompletion() {
    convertEntitiesToRecords();
    registry.flushRecords();

    // 事务同步中需要手动刷新记录
    entityManager.flush();
}

该方法虽然可行,但TransactionSynchronizationRegistry.registerInterposedSynchronization的规范指出:

The beforeCompletion callback will be invoked in the transaction
context of the transaction bound to the current thread at the time
this method is called. Allowable methods include access to resources,
e.g. Connectors. No access is allowed to "user components" (e.g. timer
services or bean methods), as these might change the state of data
being managed by the caller, and might change the state of data that
has already been flushed by another caller of
registerInterposedSynchronization. The general context is the
component context of the caller of registerInterposedSynchronization.

因此,将EntityManager和TransactionScoped bean与registerInterposedSynchronization同步机制结合使用,似乎违反了该方法的使用约定。


内容的提问来源于stack exchange,提问作者Андрей Андреев

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 15:05:07