【问题标题】:JPA entity modified by reflection not merged by entity manager由反射修改的 JPA 实体未由实体管理器合并
【发布时间】:2019-06-06 08:59:52
【问题描述】:

我需要检查我的实际实体是否与旧实体不同。

我使用反射是因为我的方法必须标准化。

对于每一列,当且仅当它不为空时,我才更新值(因为我从 CSV 读取它并且可能未指定列)。

for(Field column : fields){
   column.setAccessible(true);
   Object newValue = column.get(myObject);
   if( newValue != null && !newValue.equals(column.get(oldObject))){
      column.set(oldObject, newValue);
   }
}

this.entitymanager.merge(oldObject)

如果我进行这样的更改,则不会完成任何 UPDATE 查询。

如果我以正常方式更改值oldobject.setValue(newValue),则查询完成并更新记录。

如果我通过反射更改值,为什么实体管理器不执行 UPDATE 查询?

【问题讨论】:

  • 我认为这是因为托管实体是代理的,并且 setter 调用可以满足您的需求。我不确定这是否可能如您所愿。

标签: jpa eclipselink wildfly-15


【解决方案1】:

只需在this 找到有关此类行为的一些有用信息即可:

默认情况下,使用编织/代理 EclipseLink 使用属性更改 跟踪以检测更改。这不会检测到通过 反射字段访问(虽然方法访问是可以的)。

您可以使用@ChangeTracking 注解将默认值更改为 deferred 它将检测通过反射所做的更改。 IE。 @ChangeTracking(ChangeTrackingType.DEFERRED)

您还可以在 persistence.xml 使用,“eclipselink.weaving.changetracking”="false"

所以有几个解决方案可以尝试:

  1. 使用反射方法访问
  2. Change the ChangeTracking to deferred or even disable it
  3. Disable weaving

【讨论】:

  • 谢谢。我正在测试第一个解决方案
【解决方案2】:

感谢@Ken Chan 的回答,我更正了使用getter 和setter 的方法。

for(Field column : columns){
   Method mSet = myclass.getMethod("set"+ StringUtils.capitalize(column.getName()), column.getType());
   Method mGet = myclass.getMethod("get"+ StringUtils.capitalize(column.getName()));
   Object newValue = mGet.invoke(articolo);
   if( newValue != null && !newValue.equals(mGet.invoke(old))){
        mSet.invoke(old, newValue);
   }
 }

我必须注意方法的名称。如果实体具有属性description,则还必须有getDescription()setDescription()

现在可以了

【讨论】:

    猜你喜欢
    • 2016-02-10
    • 2013-11-13
    • 2019-12-15
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 2020-07-30
    • 2015-09-29
    • 2015-06-22
    相关资源
    最近更新 更多