【问题标题】:Modify Hibernate entity onSave修改 Hibernate 实体 onSave
【发布时间】:2020-06-14 06:19:25
【问题描述】:

登录用户创建一个项目。我想在持久化到数据库之前更新 ProjectModel 的 createdBy 字段。

@Entity
@Table(name = "PROJECTS")
@Inheritance(strategy = InheritanceType.JOINED)
public @Data class ProjectModel extends BaseModel {

    @Length(min = 4, max = 30)
    @NotNull
    private String name;

    @NotNull
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "USER_ID")
    private User createdBy;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "PROJECT_ID")
    private List<RinexFileModel> rinexFileModels;

    @Enumerated(EnumType.STRING)
    private Status status = Status.NEW;

    public void addRinexFiles(List<RinexFileModel> rinexFiles) {
        this.rinexFileModels.addAll(rinexFiles);
    }

    public void addRinexFile(RinexFileModel rinexFile) {
        this.rinexFileModels.add(rinexFile);
    }

    public enum Status {
        NEW, READY, PROCESSING, PROCESSED
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }
}

至少有两种选择。

  • 通过回调方法(@PrePersist等)类似于下面的代码,但我需要UserModel和访问spring bean

    类似这个SpringContextexample

我不喜欢这种方法,因为我认为它违反了单一责任原则。

  • 拦截器(EmptyInterceptor)

HibernateInterceptorImpl 拦截器

public class HibernateInterceptorImpl extends EmptyInterceptor {

    @Resource
    private HibernateInterceptorStrategy hibernateInterceptorStrategy;

    @Override
    public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException {
        boolean entityChanged = false;

        final EmptyInterceptor interceptor = hibernateInterceptorStrategy.getStrategy(entity);

        if (nonNull(interceptor)) {
            entityChanged = interceptor.onSave(entity, id, state, propertyNames, types);
        }

        return entityChanged;
    }
}

@Component("hibernateInterceptorStrategy")
public class HibernateInterceptorStrategy {

    @Resource
    private Map<Class, EmptyInterceptor> hibernateInterceptorStrategies;

    public EmptyInterceptor getStrategy(Object object) {
        for (Class clazz : hibernateInterceptorStrategies.keySet()) {
            if (object.getClass() == clazz) {
                return hibernateInterceptorStrategies.get(clazz);
            }
        }
        return null;
    }
}

ProjectInterceptor 实现

public class ProjectInterceptorImpl extends EmptyInterceptor {

    @Resource
    private SessionService sessionService;

    @Override
    public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException {
        final ProjectModel project = (ProjectModel) entity;

        if (isNull(project.getCreatedBy())) {
            project.setCreatedBy(sessionService.getCurrentUser());
        }

        return true;
    }
}

调试结果(用户成功添加,但在 @NotNull 验证 createdBy 时出现异常)

FIX IS:同时修改状态数组。但是对此没有好的解决方案。

【问题讨论】:

  • 你检查来自 jpa 审计的 @CreatedBy 注释吗?
  • 是的,现在可以使用

标签: java spring hibernate spring-security


【解决方案1】:

在模型保存之前填充用户数据可以使用 Spring Data @CreateBy 注释。 先检查这个article

用户 + 嵌入式类 UserPrincipal 仅更改为 UserPrincipal,因为基于用户服务返回 UserPrincipal 的弹簧安全性。所以,对于我的项目来说,将其更改为一个用户模型并不是什么大问题

启用 JPA 审计

结果

【讨论】:

    猜你喜欢
    • 2014-08-20
    • 2016-10-18
    • 2018-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-20
    • 2013-11-08
    • 1970-01-01
    相关资源
    最近更新 更多