在我的申请中,我有一个投标实体。
@Entity
@Table(name = "tender")
public class Tender {
@Id
@Column(name = "tender_id", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "name")
private String name;
@Column(name = "description")
private String description;
@OneToMany(mappedBy="tender", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JsonIgnoreProperties("tender")
private List<TenderAddress> addresses;
// constructors and getters and setters
// I am showing the setter for Address since it is customized for my requirement
public void setAddresses(List<TenderAddress> addresses) {
this.addresses = addresses;
for (TenderAddress tenderAddress : addresses) {
tenderAddress.setTender(this);
}
}
}
我的TenderAddress
实体看起来像这样。
@Entity
@Table(name = "tender_address")
public class TenderAddress {
@Id
@Column(name = "id", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="tender_id")
@JsonIgnoreProperties("addresses")
private Tender tender;
@Column(name = "address", nullable = false)
private String address;
// constructors
//getters and setters
}
在我开始测试更新操作之前,一切正常。
这是我的更新方法。
@Transactional
public Tender updateTender(Tender tender) {
Tender t = entityManager.find(Tender.class, tender.getId());
t.setName(tender.getName());
t.setDescription(tender.getDescription());
t.setAddresses(tender.getAddresses());
entityManager.merge(t);
entityManager.flush();
return findById(t.getId());
}
名称和说明已更新。我认为地址将如何更新,它将编辑相关数据库表中的当前记录。但是发生的事情是,它在表中插入了一条新记录而没有编辑已经存在的记录。事实上,我认为JPA会照顾自己。
所以,我现在的问题是,合并投标表时是否必须明确合并地址表?如果是这样,应该怎么做?
答案 0 :(得分:1)
要问的一个问题是,是否还有其他事情与TenderAddress
有关联?
如果您的问题的答案是是,那么您必须根据某些自然键而不是数据库标识符对列表进行迭代更新。这是因为您的传入列表可能是新条目和更新条目的组合,应该以特定方式合并。
如果您的问题的答案是否,那么您可以重新修改映射的注释并完成您认为可行的工作。我们不应将TenderAddress
视为实体类型,而是将其更改为@Embeddable
并将其置于@ElementCollection
内,如下所示:
@Entity
public class Tender {
@ElementCollection
private Set<TenderAddress> addresses;
}
@Embeddable
public class TenderAddress {
}
在这种情况下,您现在可以安全地替换TenderAddress
的整个集合,Hibernate将基本上根据Tender
主键从集合表执行批量删除,然后重新插入所有新的新列表中的行,这些行将与您在问题中提供的代码一起使用。