简体   繁体   中英

Saving entity tries to insert new record instead of merging with previous record

When a parent entity is persisted/merged via saveAndFlush, it tries to insert a new record for the child entity instead of finding/merging the existing record. This causes a SQLIntegrityConstraintViolationException error. I have also tried pulling the existing entity directly via the DAO, setting that to be the field in the parent entity, and then saving and flushing, and it still tries to insert a new record for the child entity field.

Any help is greatly appreciated!


Child Entity

@Entity
@Table(name = "DROPDOWN_TYPE", uniqueConstraints = {
        @UniqueConstraint(columnNames = { "DROPDOWN_TYPE_TXT" }, name = "DROPDOWN_TYPE_TXT_UK") })
public class DropdownType {

    @Id
    @Column(name = "DROPDOWN_TYPE_TXT")
    private String text;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        DropdownType that = (DropdownType) o;

        return text.equals(that.text);
    }

    @Override
    public int hashCode() {
        return text.hashCode();
    }
}

Parent Entity

@Entity
@Table(name = "DROPDOWN", uniqueConstraints = {
        @UniqueConstraint(columnNames = { "DROPDOWN_TXT", "DROPDOWN_TYPE_TXT" }, name = "DROPDOWN_UK") })
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Dropdown {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "DROPDOWN_OPTION_ID_GENERATOR")
    @SequenceGenerator(allocationSize = 1, name = "DROPDOWN_OPTION_ID_GENERATOR", sequenceName = "DROPDOWN_OPTION_ID_SQ")
    @Column(name = "DROPDOWN_OPTION_ID")
    private Long id;

    @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST })
    @JoinColumn(name = "DROPDOWN_TYPE_TXT", foreignKey = @ForeignKey(name = "DROPDOWN_TYPE_TXT_FK"))
    private DropdownType dropdownType;

    @Column(name = "DROPDOWN_TXT")
    private String text;

    @Column(name = "ACTIVE_FLG")
    private Boolean active;

    @Column(name = "LEGACY_FLG")
    private Boolean legacy;

    public Long getId() {
        return id;
    }

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

    public DropdownType getDropdownType() {
        return dropdownType;
    }

    public void setDropdownType(DropdownType dropdownType) {
        this.dropdownType = dropdownType;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public Boolean isActive() {
        return active;
    }

    public void setActive(Boolean active) {
        this.active = active;
    }

    public Boolean isLegacy() {
        return legacy;
    }

    public void setLegacy(Boolean legacy) {
        this.legacy = legacy;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Dropdown dropdown = (Dropdown) o;

        return dropdownType.equals(dropdown.dropdownType) && text.equals(dropdown.text);
    }

    @Override
    public int hashCode() {
        int result = dropdownType != null ? dropdownType.hashCode() : 0;
        result = 31 * result + (text != null ? text.hashCode() : 0);
        return result;
    }
}

If you are using hibernate as your JPA provider, be careful when you override equals and hashcode -- see this post

It may be, that your JPA provider does not consider your entities to be equal as loaded entities can be some CGLIB proxies in reality (probably better to use instanceof than to compare classes).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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