在春天

时间:2016-07-29 16:22:51

标签: json spring spring-boot spring-data spring-data-jpa

我有两个实体,OffreOffreCompetence以及它们之间的关系如下:

    @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对象,但我希望自动完成。

有什么建议吗?

谢谢你的到来。

编辑:

似乎添加新关系并更新它们是有效的,但删除它并不起作用。

1 个答案:

答案 0 :(得分:0)

我得到的最好的分离对象树(你的JSON OffreOffreCompetence如下。我的案例是2个实体,OrderOrderLine,以与你相同的方式映射。

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中实施了hashCodeOrderLine,以获得一个不那么难看的方法。