Spring JPA 保存具有复合主键的不同实体未按预期工作,更新同一实体

Spring JPA saving distinct entities with composite primary key not working as expected, updates same entity

我有一个保存一些数据的逻辑,我使用 spring boot + spring data jpa。

现在,我必须保存一个对象,过一会儿,我必须保存另一个对象。 对象的那些由三个主键属性组成。 - partCode, setCode, itemCode.

假设第一个对象有一个 toString() 返回如下:

SetItem(partCode=10-001, setCode=04, itemCode=01-0021, qty=1.0, sortNo=2, item=null)

并且第二个对象有一个 toString 在下面返回:

SetItem(partCode=10-001, setCode=04, itemCode=01-0031, qty=1.0, sortNo=2, item=null)

itemCode值不同,itemCode属性属于主键,所以两个对象不同

但在我的例子中,当我 运行 程序时,webapp 保存第一个对象,并用第二个对象值更新第一个对象,而不是单独保存对象。

(上图包含与此 post 问题不同的值)

这是我的实体信息:

/**
 * The persistent class for the set_item database table.
 *
 */
@Data
@DynamicInsert
@DynamicUpdate
@Entity
@ToString(includeFieldNames=true)
@Table(name="set_item")
@IdClass(SetGroupId.class)
public class SetItem  extends BasicJpaModel<SetItemId> {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name="PART_CODE")
    private String partCode;

    @Id
    @Column(name="SET_CODE")
    private String setCode;

    @Id
    @Column(name="ITEM_CODE")
    private String itemCode;

    private Double qty;

    @Column(name="SORT_NO")
    private int sortNo;

    @Override
    public SetItemId getId() {

        if(BooleanUtils.ifNull(partCode, setCode, itemCode)){
            return null;
        }
        return SetItemId.of(partCode, setCode, itemCode);
    }

    @ManyToMany(fetch=FetchType.LAZY)
    @JoinColumns(value = {
            @JoinColumn(name="PART_CODE", referencedColumnName="PART_CODE", insertable=false, updatable=false)
            , @JoinColumn(name="ITEM_CODE", referencedColumnName="ITEM_CODE", insertable=false, updatable=false)
    })
    private List<Item> item;

}

所以问题是, 如何单独保存对象,其中对象的复合主键部分相同。

编辑: 实体延伸到 class 以下:

@Setter
@Getter
@MappedSuperclass
@DynamicInsert
@DynamicUpdate
public abstract class BasicJpaModel<PK extends Serializable> implements Persistable<PK>, Serializable {

    @Override
    @JsonIgnore
    public boolean isNew() {
        return null == getId();
    }
}

再次编辑:可嵌入class。 有人指出可嵌入 class 后,我注意到只有两个属性,应该是三个。谢谢。

@Data
@NoArgsConstructor
@RequiredArgsConstructor(staticName="of")
@Embeddable
public class SetGroupId implements Serializable {
    //default serial version id, required for serializable classes.
    private static final long serialVersionUID = 1L;

    @NonNull
    private String partCode;

    @NonNull
    private String setCode;

}

检查如何使用 @EmbeddedId & @Embeddable(更新您可能需要在 id 字段中使用 AttributeOverrides,不确定 @Embeddable 中是否有 Column有效)。

您可以创建 class 注释 @Embeddable 并在其中添加所有这三个 ID 字段。

@Embeddable
public class MyId {
   private String partCode;
   private String setCode;
   private String itemCode;     
}

添加所需的 getter 和 setter。

然后在 class SetItem 中设置这个 class 为类似 `@EmbeddedId´ 的 id。

public class SetItem {

   @EmbeddedId
   @AttributeOverrides({
      @AttributeOverride(name="partCode",
                         column=@Column(name="PART_CODE")),
      @AttributeOverride(name="setCode",
                         column=@Column(name="SET_CODE"))
      @AttributeOverride(name="itemCode",
                         column=@Column(name="ITEM_CODE"))
   })
   MyId id;

也检查Which annotation should I use: @IdClass or @EmbeddedId

请务必在 SetGroupId 中实现 equals 和 hashCode。

你能提供 class 吗?