由反射修改的JPA实体未由实体管理器合并

由反射修改的JPA实体未由实体管理器合并,jpa,eclipselink,wildfly-15,Jpa,Eclipselink,Wildfly 15,我需要检查我的实际实体是否与旧实体不同 我使用反思,因为我的方法必须标准化 对于每个列,当且仅当值不为null时(因为我从CSV读取它,并且可能未指定列),我更新该值 如果我这样做更改,则不会执行更新查询 如果我以正常方式更改值oldobject.setValue(newValue),则完成查询并更新记录 如果我通过反射更改值,为什么实体管理器不执行更新查询?请在以下位置查找有关此类行为的一些好信息: 默认情况下,在使用编织/代理时,EclipseLink使用属性更改 跟踪以检测更改。这将检测不

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

我使用反思,因为我的方法必须标准化

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

如果我这样做更改,则不会执行更新查询

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


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

请在以下位置查找有关此类行为的一些好信息:

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

您可以使用@ChangeTracking注释将默认值更改为 延迟,它将检测通过反射进行的更改。即 @ChangeTracking(ChangeTrackingType.DEFERRED)

您还可以在中禁用编织或编织更改跟踪 persistence.xml使用“eclipselink.weaving.changetracking”=“false”

因此,有两种解决方案可以尝试:

  • 使用反射方法访问

  • 只需在以下网址查找有关此类行为的一些好信息:

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

    您可以使用@ChangeTracking注释将默认值更改为 延迟,它将检测通过反射进行的更改。即 @ChangeTracking(ChangeTrackingType.DEFERRED)

    您还可以在中禁用编织或编织更改跟踪 persistence.xml使用“eclipselink.weaving.changetracking”=“false”

    因此,有两种解决方案可以尝试:

  • 使用反射方法访问

  • 感谢@Ken Chan answer,我使用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()


    现在它工作了

    感谢@Ken Chan answer,我使用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()


    现在它可以工作了

    我认为这是因为托管实体是代理的,setter调用可以满足您的需要。我不确定这是否是您想要的方式。我认为这是因为托管实体是代理的,setter调用可以满足您的需要。我不确定这是否是你想要的方式。谢谢。我正在测试第一个解决方案谢谢。我正在测试第一个解决方案