简体   繁体   English

JPA / Hibernate - 在子更改时更新父实体

[英]JPA / Hibernate - Update parent entity on child changes

I have following two entities in OneToOne relationship.我在 OneToOne 关系中有两个实体。

@Entity
@Audited
public class Parent implements Serializable {

    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid2")
    @Size(max = 36)
    @Column(length = 36)
    private String id;

    @NotNull
    private String createdUser;

    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    @Temporal(TemporalType.TIMESTAMP)
    @NotNull
    private Date createdDate;

    private String modifiedUser;

    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    @Temporal(TemporalType.TIMESTAMP)
    private Date modifiedDate;

    @OneToOne(targetEntity = Child.class, optional = false, fetch = FetchType.EAGER, cascade = { CascadeType.ALL }, orphanRemoval = true)
    @Fetch(FetchMode.JOIN)
    private Child child = new Child();

    @PrePersist
    public void prePersist() {

        createdDate = new Date();
        createdUser = "SampleUser";

    }

    @PreUpdate
    public void preUpdate() {

        modifiedDate = new Date();
        modifiedUser = "SampleUser";

    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getCreatedUser() {
        return createdUser;
    }

    public void setCreatedUser(String createdUser) {
        this.createdUser = createdUser;
    }

    public Date getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(Date createdDate) {
        this.createdDate = createdDate;
    }

    public String getModifiedUser() {
        return modifiedUser;
    }

    public void setModifiedUser(String modifiedUser) {
        this.modifiedUser = modifiedUser;
    }

    public Date getModifiedDate() {
        return modifiedDate;
    }

    public void setModifiedDate(Date modifiedDate) {
        this.modifiedDate = modifiedDate;
    }

    public Child getChild() {
        return child;
    }

    public void setChild(Child child) {
        this.child = child;
    }
}
@Entity
@Audited
public class Child implements Serializable {

    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid2")
    @Size(max = 36)
    @Column(length = 36)
    private String id;

    private String sampleField;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getSampleField() {
        return sampleField;
    }

    public void setSampleField(String sampleField) {
        this.sampleField = sampleField;
    }
}

Now I need to update the parents modified (date & user) fields.现在我需要更新父母修改(日期和用户)字段。 If i change only the field (sampleField) in the child then the modified fields are not updated in the parent.如果我只更改子项中的字段(sampleField),则修改后的字段不会在父项中更新。

I found following two statements and if I understand it correctly then its not a good idea to change the parent in lifecycle events (Interceptor, EventListener, Callbacks) of the child.我发现以下两个语句,如果我理解正确,那么在孩子的生命周期事件(Interceptor、EventListener、Callbacks)中更改父级不是一个好主意。

Statement 1 Statement 2声明 1声明 2

What is a save way to address my problem?解决我的问题的保存方法是什么?

I can only offer you a workaround, as I don't think what you want to achieve is doable out of the box with Hibernate or any other JPA provider.我只能为您提供一种解决方法,因为我认为您想要实现的目标无法通过 Hibernate 或任何其他 JPA 提供程序开箱即用。

You can encapsulate the Child completely, and with a bi-directional reference, you can make sure that the modifiedDate is dirtied when necessary.您可以完全封装Child ,并使用双向引用,您可以确保 modifiedDate 在必要时被弄脏。 A model similar to this should suffice:与此类似的 model 就足够了:

@Entity
@Audited
public class Parent implements Serializable {

    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid2")
    @Size(max = 36)
    @Column(length = 36)
    private String id;

    @NotNull
    private String createdUser;

    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    @Temporal(TemporalType.TIMESTAMP)
    @NotNull
    private Date createdDate;

    private String modifiedUser;

    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
    @Temporal(TemporalType.TIMESTAMP)
    private Date modifiedDate;

    @OneToOne(targetEntity = Child.class, optional = false, fetch = FetchType.EAGER, cascade = { CascadeType.ALL }, orphanRemoval = true)
    @Fetch(FetchMode.JOIN)
    private Child child;

    public Parent() {
        child = new Child(this);
    }

    @PrePersist
    public void prePersist() {
        createdDate = modifiedDate = new Date();
        createdUser = modifiedUser = "SampleUser";
        
    }

    @PreUpdate
    public void preUpdate() {
        modifiedDate = new Date();
        modifiedUser = "SampleUser";
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getCreatedUser() {
        return createdUser;
    }

    public void setCreatedUser(String createdUser) {
        this.createdUser = createdUser;
    }

    public Date getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(Date createdDate) {
        this.createdDate = createdDate;
    }

    public String getModifiedUser() {
        return modifiedUser;
    }

    public void setModifiedUser(String modifiedUser) {
        this.modifiedUser = modifiedUser;
    }

    public Date getModifiedDate() {
        return modifiedDate;
    }

    public void setModifiedDate(Date modifiedDate) {
        this.modifiedDate = modifiedDate;
    }

    public Child getChild() {
        return child;
    }

    // Note that I removed the setter
}
@Entity
@Audited
public class Child implements Serializable {

    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid2")
    @Size(max = 36)
    @Column(length = 36)
    private String id;

    private String sampleField;

    @OneToOne(mappedBy = "child")
    private Parent parent;

    public Child() {}

    public Child(Parent parent) {
        this.parent = parent;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getSampleField() {
        return sampleField;
    }

    public void setSampleField(String sampleField) {
        if (parent != null && !Objects.equals(this.sampleField, sampleField)) {
            parent.setModifiedDate(null);
        }
        this.sampleField = sampleField;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM