当前位置: 首页 > 知识库问答 >
问题:

EclipseLink 不会检测在 @PreUpdate 内部使用反射进行的更新

水睿
2023-03-14

我想在我的应用中注册对某个实体所做的更改;我希望它在JPA的不同实现之间是可移植的,所以我不能使用Envers(Hibernate)或History Policy(EclipseLink)这样的框架。

所以我向我的实体添加了一个 changeLog 字段,我正在使用带有@PreUpdate@PrePersist注释的实体侦听器来更新此字段。

问题是,我想使用注释来指示应该存储这些更改的字段,而不是使用字段的固定名称。当我使用反射来更新这个字段而不是直接使用set方法时,Eclipse Link似乎无法检测到变更日志字段中的更改,因此,它不在生成的UPDATE语句中

@PreUpdate
@PrePersist
public void updateChangeLog(Object auditable) throws IllegalAccessException {
    Field[] fields = auditable.getClass().getDeclaredFields();
    Field changeLogField = null;

    for (Field field : fields) {
        if (field.getAnnotation(ChangeLog.class) != null) {
            field.setAccessible(true);
            changeLogField = field;
        }
    }


    String changeLog = generateChangeLog();


    // This works
    // ((MyEntity)auditable).setChangeLog(changeLog);

    // This doesn't work!
    changeLogField.set(auditable, changeLog);
}

这是EclipseLink中的一个错误还是预期的行为?有没有办法将< code>changelog字段标记为dirty,以便EclipseLink更新它的值?

共有1个答案

康赞
2023-03-14

出于性能原因,EclipseLink的编织默认使用变更跟踪。这意味着直接对字段进行的更改将不会生效。您可以使用访问器方法来更改这些值,这些方法将被更改监听器获取。否则,您必须关闭更改跟踪,如下所述:http://eclipse . org/eclipse link/documentation/2.5/JPA/extensions/a _ change tracking . htm

或关闭编织。

 类似资料:
  • 问题内容: 我在StackOverflow上遇到了类似的问题,尝试了解决方案,但没有找到答案。 我正在使用一种相当通用的JPA策略来设置某些实体的上次修改时间。设置列和字段,然后使用标记方法,并将其设置为等于当前时间。 问题是,我可以在调试器中看到正在调用该方法并且该字段正在更新,但是在我的数据库日志中,我仅看到一个SQL调用,以UPDATE更改字段,其中不包含timestamp字段的UPDATE

  • 问题内容: 在我的应用程序中,我定义了以下类: 如果我尝试将新帖子添加到论坛实体,则数据库将通过回调正确更新字段。但是,如果我尝试使用以下代码更新发布实体: 仅帖子数据被更新,字段值不变。我认为方法应该有效,并更新论坛实体。这是错误还是我错过了什么? 问题答案: 这不是错误,即使快速尝试也可以达到您预期的效果。不利的消息是由于以下原因,不能保证它能正常工作: 从JPA 2.0规范的第93页: 通常

  • 问题内容: 具体来说,我正在尝试为需要用于在Windows和Unix上构建路径的方法创建单元测试。该代码必须在两个平台上都可以运行,但是当我尝试更改此static final字段时,却遇到了JUnit错误。 任何人都知道发生了什么事吗? 当我这样做时,我得到 有什么想法吗? 问题答案: 从文档中: 如果基础字段是final,则该方法将为该字段成功地抛出除非, 并且该字段是非静态的 。 因此,在第一

  • 我有一个Jqgrid,Dinamicly生成如下所示的选择:

  • 我在试验Eclipselink。我正在尝试更新数据库中的一个现有实体。JPA实体只有公共字段,字段使用JPA注释进行注释。代码使用加载实体。 代码创建JPA实体的实例,为实体的公共字段赋值,并调用EntityManager.merge(entity)方法。Eclipselink不更新数据库记录。我启用了log来查看Eclipselink是否发出SQL语句。 Eclipselink不发出任何upda

  • 我正在使用反射来调用java.util.Stream.Stream上的方法,但由于实际实现(ReferencePipeline等)具有运行的实际代码,因此在调用时会收到非法的反射访问警告,如果没有该调用,它将无法工作。我想知道是否有一种方法可以自动将其委托给一个访问不非法的超级方法?也就是说,我想调用,其中是合法的,而不是或任何实现。 编辑这里是一些代码。是通过反射获得的流的具体实例。