我有两个实体,Offre
和OffreCompetence
以及它们之间的关系如下:
@OneToMany(mappedBy="offre",cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Collection<OffreCompetence> offreCompetences;
因此每个Offre
实体都有许多OffreCompetence
个实体。
我们假设我有一个&#39; Offre&#39;如下:
{
"codeOffre": 144,
"titre": "Testable 999",
"offreCompetences": [
{
"codeOffreCompetence": 93,
"niveauRequis": "77",
"competence": {
"codeCompetence": 17,
"titre": "Administrateur Mainframe IBM",
"activated": true
}
},
{
"codeOffreCompetence": 94,
"niveauRequis": "88",
"competence": {
"codeCompetence": 18,
"titre": "Administrateur Autres Systèmes",
"activated": true
}
},
{
"codeOffreCompetence": 95,
"niveauRequis": "99",
"competence": {
"codeCompetence": 19,
"titre": "Concepteur UML, Merise, ...",
"activated": true
}
},
{
"codeOffreCompetence": 96,
"niveauRequis": "88",
"competence": {
"codeCompetence": 18,
"titre": "Administrateur Autres Systèmes",
"activated": true
}
},
{
"codeOffreCompetence": 97,
"niveauRequis": "99",
"competence": {
"codeCompetence": 17,
"titre": "Administrateur Mainframe IBM",
"activated": true
}
}
],
"ville": {
"codeVille": 2
},
"typeContrat": {
"codeTypeContrat": 3
}
}
然后我想要更新此Offre
,因此我调用了一个put方法,该方法需要一个&#39; Offre&#39;作为一个参数,这个方法会调用业务代码来更新这个&#39; Offre&#39;,这是更新这个实体的方法:
public Offre updateOffre(Offre offre) {
for(OffreCompetence offreCompetence : offre.getOffreCompetences()) {
offreCompetence.setOffre(offre);
}
return offreRepository.saveAndFlush(offre);
}
所以我发送这个新的json,删除了一些&#39; OffreCompetence&#39;关系,我添加了一个新的:
{
"codeOffre": 144,
"titre": "Testable 999",
"offreCompetences": [
{
"codeOffreCompetence": 96,
"niveauRequis": "88",
"competence": {
"codeCompetence": 18
}
},
{
"niveauRequis": "5",
"competence": {
"codeCompetence": 17
}
}
],
"ville": {
"codeVille": 2
},
"typeContrat": {
"codeTypeContrat": 3
}
}
这里的问题是它将这两个关系作为新关系添加到旧关系中,因为您可以看到我删除了一个并更新了一个并删除了一个,因此更新后的Offre
应该只包含我发送的关系。
我在设置新关系之前已经考虑过使用服务方法删除旧关系,该服务方法会搜索与Offre
的所有关系并删除它们然后添加我发送的关系。 Offre
对象,但我希望自动完成。
有什么建议吗?
谢谢你的到来。
似乎添加新关系并更新它们是有效的,但删除它并不起作用。
答案 0 :(得分:0)
我得到的最好的分离对象树(你的JSON Offre
和OffreCompetence
如下。我的案例是2个实体,Order
和OrderLine
,以与你相同的方式映射。
Order.java
@Entity
@Table(name = "ORDERS")
public class Order implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ORDER_ID")
private Long id;
// ... basic attributes
// same mapping as in your use case
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<OrderLine> orderLines;
/* getters and setters */
}
OrderLine.java
@Entity
@Table(name = "ORDER_LINES")
public class OrderLine implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ORDER_LINE_ID")
private Long id;
// ... basic attributes
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "ORDER_ID")
private Order order;
/* getters and setters */
/* equals and hashCode */
}
持久化根节点及其子节点是这样完成的:
@Override
public Order findWithReference(String reference) {
List<Order> list = em.createQuery("SELECT o FROM Order o WHERE o.reference = :reference")
.setParameter("reference", reference).getResultList();
if (list.isEmpty()) {
return null;
} else if (list.size() == 1) {
return list.get(0);
} else {
throw new IllegalStateException(String.format("The reference '%s' should uniquely identify an order.", reference));
}
}
@Override
public Order save(Order order) {
Order managed = findWithReference(order.getReference());
if (managed == null) {
em.persist(order);
return order;
} else {
// remove obsolete children and children existing both in detached and managed entity
for (Iterator<OrderLine> iter = managed.getOrderLines().iterator(); iter.hasNext();) {
OrderLine managedOrderLine = iter.next();
if (!order.getOrderLines().contains(managedOrderLine)) {
iter.remove();
em.remove(managedOrderLine);
} else {
order.getOrderLines().remove(managedOrderLine);
}
}
order.setId(managed.getId());
return em.merge(order);
}
}
合并产生令人满意的结果的技巧是从托管实体中删除过时的子项,并从已分离的实例中删除已存在的子项。为了匹配孩子,我在equals
中实施了hashCode
和OrderLine
,以获得一个不那么难看的方法。