【问题标题】:Cloning JPA entity including value annotated with spring's createdBy克隆 JPA 实体,包括用 spring 的 createdBy 注释的值
【发布时间】:2019-01-21 04:40:39
【问题描述】:

我有以下超类(抽象)

public abstract class AbstractAuditEntity {
  @CreatedBy
  private String createdBy;
}

我的数据库中有几个对象。现在我想要一种方法来克隆特定对象及其所有属性,包括 createdBy。我可以将任何 String 设置为此值,但该值会在持久化到数据库之前重置为当前经过身份验证的用户名。

如何防止 spring/jpa 在已填充时覆盖我的 createdBy 字段?

提前致谢!

【问题讨论】:

    标签: java spring jpa audit


    【解决方案1】:

    不幸的是,这似乎是不可能的。

    在 AuditingEntityListener 中,@PrePersist 方法如下所示:

    @PrePersist
    public void touchForCreate(Object target) {
    
        Assert.notNull(target, "Entity must not be null!");
    
        if (handler != null) {
    
            AuditingHandler object = handler.getObject();
            if (object != null) {
                object.markCreated(target);
            }
        }
    }
    

    然后是 AuditingHandler:

    public <T> T markCreated(T source) {
    
        Assert.notNull(source, "Entity must not be null!");
    
        return touch(source, true);
    }
    

    由于第二个参数为真,它总是会设置 createdBy 字段:

    private Optional<Object> touchAuditor(AuditableBeanWrapper<?> wrapper, boolean isNew) {
    
        Assert.notNull(wrapper, "AuditableBeanWrapper must not be null!");
    
        return auditorAware.map(it -> {
    
            Optional<?> auditor = it.getCurrentAuditor();
    
            Assert.notNull(auditor,
                    () -> String.format("Auditor must not be null! Returned by: %s!", AopUtils.getTargetClass(it)));
    
            auditor.filter(__ -> isNew).ifPresent(foo -> wrapper.setCreatedBy(foo));
            auditor.filter(__ -> !isNew || modifyOnCreation).ifPresent(foo -> wrapper.setLastModifiedBy(foo));
    
            return auditor;
        });
    }
    

    但由于这似乎是一个有趣的功能,您应该继续并打开未来的请求: https://jira.spring.io/projects/DATAJPA/issues/DATAJPA-1397?filter=allopenissues

    【讨论】:

    • 是的,我看到了 touchAuditor-Method。所以解决这个问题的唯一方法(到目前为止)是在没有 jpa 的情况下将对象直接保存到数据库,对吧?不过,谢谢你的回答!
    • 是的,或者您创建自己的 JPA 侦听器并设置用户。
    【解决方案2】:

    我为 DataJPA 创建了一个功能请求,但我不知道它何时(如果)得到解决。

    在此之前,我先保存实体并使用本机 SQL 更改 createdBy。我不会将此标记为已接受的答案。

    public interface EntityRepository {
      @Transactional(propagation = NESTED)
      @Modifying
      @Query(value = "UPDATE entity_table SET created_by = ? WHERE id = ?", nativeQuery = true)
      void updateSignalRequestCreatedBy(String createdBy, long signalRequestId);
    }
    

    Source DataJPA-Request

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-20
      • 1970-01-01
      相关资源
      最近更新 更多