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

EclipseLink 2.6.4多Merge后提交无UPDATE执行问题排查求助

我们使用EclipseLink 2.6.4结合JTA,配置了eclipselink.persistence-context.flush-mode=commit。在对多个不同对象执行merge操作后提交事务时,发现ODSMaterialLot对象没有触发数据库UPDATE(其他持久化操作如INSERT、其他实体的UPDATE正常),且已确认新值与数据库原有数据不同。

业务逻辑中存在多次事务启停,该事务前后的其他提交均正常。若每次merge后立即提交事务,ODSMaterialLot的UPDATE可正常执行,但这种方式无法保证操作原子性(失败时无法回滚所有动作),因此不可行。

已开启EclipseLink FINEST级别日志,两种场景的日志片段如下:

场景1:多次查询+Merge后一次性提交(无ODSMaterialLot的UPDATE SQL)

[EL Finer]: 2025-01-17 17:15:23.065--UnitOfWork(1790824463)--Thread(Thread[HTTP Worker [@1421579142],5,Dedicated_Application_Thread])--begin unit of work commit
[EL Finer]: 2025-01-17 17:15:23.065--ClientSession(551861325)--Thread(Thread[HTTP Worker [@1421579142],5,Dedicated_Application_Thread])--TX beginTransaction, status=STATUS_ACTIVE
[EL Finest]: 2025-01-17 17:15:23.065--UnitOfWork(1790824463)--Thread(Thread[HTTP Worker [@1421579142],5,Dedicated_Application_Thread])--Execute query UpdateObjectQuery(movilitas.com.archiving.jpa.entity.archive.ArchivingManagement@4633dca9)
[EL Finest]: 2025-01-17 17:15:23.066--UnitOfWork(1790824463)--Thread(Thread[HTTP Worker [@1421579142],5,Dedicated_Application_Thread])--Execute query InsertObjectQuery(movilitas.com.archiving.jpa.entity.archive.ArchivingData@1f0b544c)
[EL Fine]: 2025-01-17 17:15:23.066--ClientSession(551861325)--Connection(938909931)--Thread(Thread[HTTP Worker [@1421579142],5,Dedicated_Application_Thread])--INSERT INTO O95_ARCH_DATA (UIID, ARCH_TYPE, CHANGEDBY, CHANGEDON, CREATEDBY, CREATEDON, HISTORY, OBJECT_ID, OBJECT_JSON, OBJECT_NAME, OBJECT_RAW, OBJECT_XML, STATUS, TENANT, ARCH_MGMT) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  bind => [961, RAW, Guest, 2025-01-17 17:15:23.039, Guest, 2025-01-17 17:15:23.039, WIP->ODS_DIRTY, ELE_MaterialLot_10, null, MaterialLot, [B@34807356, null, ODS_DIRTY, default, 761]
[EL Finest]: 2025-01-17 17:15:23.067--UnitOfWork(1790824463)--Thread(Thread[HTTP Worker [@1421579142],5,Dedicated_Application_Thread])--Execute query UpdateObjectQuery(movilitas.com.archiving.jpa.entity.archive.material.materialLot.ODSMaterialLot@348b939e)
[EL Finest]: 2025-01-17 17:15:23.067--UnitOfWork(1790824463)--Thread(Thread[HTTP Worker [@1421579142],5,Dedicated_Application_Thread])--Execute query UpdateObjectQuery(movilitas.com.archiving.jpa.entity.archive.material.materialLot.ODSMaterialLotProperty@6f21d04d)
[EL Finest]: 2025-01-17 17:15:23.067--UnitOfWork(1790824463)--Thread(Thread[HTTP Worker [@1421579142],5,Dedicated_Application_Thread])--Execute query UpdateObjectQuery(movilitas.com.archiving.jpa.entity.archive.material.materialLot.ODSMaterialLotProperty@29ecc706)
[EL Finest]: 2025-01-17 17:15:23.068--ServerSession(101077745)--Connection(981032147)--Thread(Thread[HTTP Worker [@1421579142],5,Dedicated_Application_Thread])--Connection released to connection pool [default].
[EL Finer]: 2025-01-17 17:15:23.069--UnitOfWork(1790824463)--Thread(Thread[HTTP Worker [@1421579142],5,Dedicated_Application_Thread])--TX afterCompletion callback, status=COMMITTED
[EL Finest]: 2025-01-17 17:15:23.075--ServerSession(101077745)--Thread(Thread[HTTP Worker [@1421579142],5,Dedicated_Application_Thread])--Propagating command asynchronously
[EL Finer]: 2025-01-17 17:15:23.077--UnitOfWork(1790824463)--Thread(Thread[HTTP Worker [@1421579142],5,Dedicated_Application_Thread])--end unit of work commit

场景2:每次Merge后立即提交(正常生成ODSMaterialLot的UPDATE SQL)

[EL Finer]: 2025-01-17 17:39:16.277--UnitOfWork(1013035015)--Thread(Thread[HTTP Worker [@1540943114],5,Dedicated_Application_Thread])--begin unit of work commit
[EL Finer]: 2025-01-17 17:39:16.277--ClientSession(1157391672)--Thread(Thread[HTTP Worker [@1540943114],5,Dedicated_Application_Thread])--TX beginTransaction, status=STATUS_ACTIVE
[EL Finest]: 2025-01-17 17:39:16.277--UnitOfWork(1013035015)--Thread(Thread[HTTP Worker [@1540943114],5,Dedicated_Application_Thread])--Execute query UpdateObjectQuery(movilitas.com.archiving.jpa.entity.archive.material.materialLot.ODSMaterialLot@339a518b)
[EL Finest]: 2025-01-17 17:39:16.277--ServerSession(1735080251)--Connection(662352849)--Thread(Thread[HTTP Worker [@1540943114],5,Dedicated_Application_Thread])--Connection acquired from connection pool [default].
[EL Finest]: 2025-01-17 17:39:16.277--ClientSession(1157391672)--Thread(Thread[HTTP Worker [@1540943114],5,Dedicated_Application_Thread])--reconnecting to external connection pool
[EL Fine]: 2025-01-17 17:39:16.277--ClientSession(1157391672)--Connection(1173906560)--Thread(Thread[HTTP Worker [@1540943114],5,Dedicated_Application_Thread])--UPDATE O95_MALT SET CHANGEDON = ?, CUST01 = ?, CUST02 = ?, CUST03 = ?, CUST04 = ?, CUST05 = ?, CUST06 = ? WHERE (UIID = ?)
  bind => [2025-01-15 09:58:40.623, 0, 1, 2, 3, 4, 5, 39013]
[EL Finest]: 2025-01-17 17:39:16.281--ServerSession(1735080251)--Connection(662352849)--Thread(Thread[HTTP Worker [@1540943114],5,Dedicated_Application_Thread])--Connection released to connection pool [default].
[EL Finer]: 2025-01-17 17:39:16.282--UnitOfWork(1013035015)--Thread(Thread[HTTP Worker [@1540943114],5,Dedicated_Application_Thread])--TX afterCompletion callback, status=COMMITTED

两种场景上下文和数据完全一致,已尝试EntityManager.clear()无效,提交前实体字段均为更新后的值,但提交后数据库无更新,新线程查询返回旧值。


根因分析

从日志对比可以看出,场景1中EclipseLink触发了UpdateObjectQuery但未生成对应的SQL UPDATE语句,说明EclipseLink认为ODSMaterialLot实体没有变更需要同步到数据库,但实际业务中实体已被修改。可能的核心原因如下:

  1. 实体变更未被正确追踪

    • 如果merge操作后,修改的是原来的detached实体而非merge返回的managed实体,EclipseLink的变更检测机制无法感知到修改(仅managed实体的变更会被追踪)。
    • 若merge后执行了针对ODSMaterialLot的查询(如find),可能从一级缓存/二级缓存加载旧实体,覆盖已修改的managed实体。
  2. 查询或实体设置了只读属性

    • 如果查询ODSMaterialLot时使用了eclipselink.read-only=true的查询提示,或实体类标注了@ReadOnly,即使执行merge,EclipseLink也不会追踪该实体的变更,提交时不会生成UPDATE。
  3. EclipseLink 2.6.4版本BUG

    • 2.6.4是较老版本,存在多事务、多merge混合场景下的变更检测BUG,可能导致变更丢失。
  4. 二级缓存干扰

    • 若启用了二级缓存,缓存中的旧实体可能在merge后被加载,覆盖当前事务中的变更,导致EclipseLink认为实体未修改。

解决方案

1. 规范Merge操作流程

确保修改的是merge返回的managed实体,而非原始的detached实体:

// 正确方式
ODSMaterialLot detachedLot = ...; // 从外部获取的脱离上下文实体
ODSMaterialLot managedLot = entityManager.merge(detachedLot);
managedLot.setCust01(0); // 修改托管实体的属性
managedLot.setCust02(1);
// ...其他修改

2. 检查并移除只读设置

  • 排查所有查询ODSMaterialLot的代码,确保没有设置eclipselink.read-only提示;
  • 检查ODSMaterialLot实体类,确认没有标注@ReadOnly注解;
  • 若必须使用只读查询,在需要更新的场景中覆盖该设置:
    Query query = entityManager.createQuery("SELECT l FROM ODSMaterialLot l WHERE l.uiid = :uiid");
    query.setParameter("uiid", uiid);
    query.setHint("eclipselink.read-only", false); // 强制关闭只读
    ODSMaterialLot lot = (ODSMaterialLot) query.getSingleResult();
    

3. 禁用/刷新二级缓存

  • 临时禁用二级缓存(在persistence.xml中设置<shared-cache-mode>NONE</shared-cache-mode>),验证是否解决问题;
  • 若确认是缓存问题,在merge后手动清除该实体的缓存:
    entityManager.getEntityManagerFactory().getCache().evict(ODSMaterialLot.class, lotUiid);
    

4. 升级EclipseLink版本

将EclipseLink升级到2.6.x系列的最新版本(如2.6.10),或直接升级到更高的稳定版本(如2.7.x),修复旧版本的已知BUG。

5. 启用变更检测日志

在persistence.xml中添加以下配置,获取更详细的变更检测日志,定位具体问题:

<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.logging.level.sql" value="FINE"/>
<property name="eclipselink.logging.level.transaction" value="FINE"/>
<property name="eclipselink.logging.level.cache" value="FINE"/>

内容的提问来源于stack exchange,提问作者EmilienLF

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 19:39:49