使用 EmbeddedId 将元素添加到集合时,Hibernate 不会设置修改标志

问题描述 投票:0回答:0

这是我在使用 hibernate envers 5.6.15 时遇到的问题的一个小说明。

我有一个父实体,有两种孩子:儿子和女儿。

@Entity
@Table(name = "PARENT")
@Data
@Audited
public class Parent {

    @Id
    @GeneratedValue(generator = "UUID")
    @GenericGenerator(
            name = "UUID",
            strategy = "org.hibernate.id.UUIDGenerator"
    )
    @Column(name = "PARENT_ID", nullable = false, updatable = false)
    private String parentId;

    @Column(name = "NAME")
    @Audited(withModifiedFlag = true, modifiedColumnName = "NAME_MOD")
    private String name;

    @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, mappedBy = "parent", orphanRemoval = true)
    @Audited(withModifiedFlag = true, modifiedColumnName = "DAUGHTERS_MOD")
    private Set<Daughter> daughters = new HashSet<>();

    @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, mappedBy = "key.parent", orphanRemoval = true)
    @Audited(withModifiedFlag = true, modifiedColumnName = "SONS_MOD")
    private Set<Son> sons = new HashSet<>();

    public void setDaughters(Collection<Daughter> daughters) {
        this.daughters.clear();
        daughters.forEach(daughter -> daughter.setParent(this));
        this.daughters.addAll(daughters);
    }


    public void addDaughter(Daughter daughter) {
        daughter.setParent(this);
        this.daughters.add(daughter);
    }

    public void setSons(Collection<Son> sons) {
        this.sons.clear();
        sons.forEach(son -> son.setParent(this));
        this.sons.addAll(sons);
    }


    public void addSon(Son son) {
        son.setParent(this);
        this.sons.add(son);
    }
}

女儿正在使用生成的 ID

@Table(name = "DAUGHTER")
@Data
@Audited
@Entity
@NoArgsConstructor
public class Daughter {

    @Id
    @GeneratedValue(generator = "UUID")
    @GenericGenerator(
            name = "UUID",
            strategy = "org.hibernate.id.UUIDGenerator"
    )
    @Column(name = "DAUGHTER_ID", nullable = false, updatable = false)
    private String daughterId;

    @ManyToOne(optional = false)
    @JoinColumn(name = "PARENT_ID")
    private Parent parent;

    @Audited(withModifiedFlag = true, modifiedColumnName = "NAME_MOD")
    private String name;

    public Daughter(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Daughter daughter = (Daughter) o;
        return Objects.equals(daughterId, daughter.daughterId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(getClass());
    }
}

当 Son 使用嵌入 ID 时

@Entity
@Audited
@Table(name = "SON")
@Data
public class Son {

    @EmbeddedId
    private SonKey key = new SonKey();

    @Audited(withModifiedFlag = true, modifiedColumnName = "AGE_MOD")
    private Integer age;


    public void setParent(Parent parent) {
        getKey().setParent(parent);
    }

    public void setName(String name) {
        getKey().setName(name);
    }
}

@Embeddable
@Data
public class SonKey implements Serializable {

    private static final long serialVersionUID = 14685116845125446L;

    @ManyToOne(optional = false)
    @JoinColumn(name = "PARENT_ID")
    private Parent parent;

    @Column(name = "NAME")
    private String name;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        SonKey key = (SonKey) o;
        return Objects.equals(parent.getParentId(), key.getParent().getParentId()) && Objects.equals(name, key.getName());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getClass());
    }
}

如果我添加女儿或儿子,恩弗斯的行为会有所不同。在前一种情况下,修改后的标志设置为 true,而在后者中则不然。

结果,这样的测试通过了

    @Test
    void shouldReturnChangedFields() {
        Parent parent = new Parent();
        parent.setName("Anakin");

        tx.execute((___) -> {
            em.persist(parent);
            return parent;
        });
        parent.setName("Darth vader");
        parent.addDaughter(new Daughter("Leia"));
        Son son = new Son();
        son.setName("Luke");
        son.setAge(5);
        parent.addSon(son);

        tx.execute((___) -> {
            em.merge(parent);
            return parent;
        });

        List revisionsWithChanges = tx.execute((___) -> getRevisionsWithChangesForParent(parent.getParentId()));

        assertThat(((Object[]) revisionsWithChanges.get(1))[3]).isEqualTo(newHashSet("name", "daughters"));
    }

    private List getRevisionsWithChangesForParent(String parentId) {
        AuditQuery auditQuery = auditReader.createQuery().forRevisionsOfEntityWithChanges(Parent.class, false)
                .add(AuditEntity.id().eq(parentId));
        return auditQuery.getResultList();
    }

我希望这两种情况的行为相同。我也尝试过在

@MapsId
中使用
Son
但没有成功。

这是你所期待的吗?我是不是做错了什么?

hibernate-envers
© www.soinside.com 2019 - 2024. All rights reserved.