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 吗?
我有一个保存一些数据的逻辑,我使用 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 吗?