【问题标题】:Spring JPA saving distinct entities with composite primary key not working as expected, updates same entitySpring JPA保存具有复合主键的不同实体未按预期工作,更新相同实体
【发布时间】:2018-04-07 18:53:32
【问题描述】:

我有一个保存一些数据的逻辑,我使用 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 会保存第一个对象,并使用第二个对象值更新第一个对象,而不是单独保存对象。

(上图包含与此帖子​​问题不同的值)

这是我的实体信息:

/**
 * 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;

}

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

编辑: 实体在类下面扩展:

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

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

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

@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;

}

【问题讨论】:

    标签: spring jpa composite-primary-key persist


    【解决方案1】:

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

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

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

    添加所需的 getter 和 setter。

    然后在SetItem这个类中设置这个类的id,比如`@EmbeddedId´。

    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

    【讨论】:

    • 谢谢。我看到了我的可嵌入类。而且只有两个属性,而不是三个。所以我会改变这个,看看会发生什么。真的谢谢你。
    【解决方案2】:

    一定要在 SetGroupId 中实现 equals 和 hashCode。

    你能提供那个课程吗?

    【讨论】:

    • 好主意,谢谢。我也会实现这些方法
    猜你喜欢
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-26
    • 1970-01-01
    • 2018-12-27
    相关资源
    最近更新 更多