【问题标题】:Spring Data JPA: one-to-one instantiation problem: PersistentObjectException: detached entity passed to persistSpring Data JPA:一对一实例化问题:PersistentObjectException:分离实体传递给持久化
【发布时间】:2019-12-10 10:50:13
【问题描述】:

我正在编写一个简单的 Order-Payment 一对一关联:

订单类相关代码:

@Entity
public class Order implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    (...)   

    @OneToOne(cascade=CascadeType.ALL, mappedBy="order")
    private Payment payment;

支付类相关代码:

@Entity
public class Payment implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne
    @MapsId 
    private Order order;

然后我想实现一个基本方法来使用 Spring Data JPA 存储库为我的测试数据库播种,但如果我尝试以下代码,我会得到一个 PersistentObjectExceptiondetached entity passed to persist

Order o1 = new Order(null, Instant.parse("2019-06-20T19:53:07Z"));
orderRepository.save(o1);
Payment p1 = new Payment(null, Instant.parse("2019-06-23T13:02:55Z"), o1);
paymentRepository.save(p1);

如果我尝试这种方式也会出现同样的问题:

Order o1 = new Order(null, Instant.parse("2019-06-20T19:53:07Z"));
Payment p1 = new Payment(null, Instant.parse("2019-06-23T13:02:55Z"), o1);
orderRepository.save(o1);
paymentRepository.save(p1);

它的唯一工作方式如下:

Order o1 = new Order(null, Instant.parse("2019-06-20T19:53:07Z"));
Payment p1 = new Payment(null, Instant.parse("2019-06-23T13:02:55Z"), o1);
o1.setPayment(p1);
orderRepository.save(o1);
paymentRepository.save(p1);

我想了解为什么只有最后一种方法有效。在多对一关联中,我不必在保存之前设置双向关联即可工作。在这种情况下,我对分离实体的行为缺少什么?谢谢。

【问题讨论】:

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


    【解决方案1】:

    试试这个,

    Order o1 = new Order(null, Instant.parse("2019-06-20T19:53:07Z"));
    Payment p1 = new Payment(null, Instant.parse("2019-06-23T13:02:55Z"), o1);
    o1.setPayment(p1);
    orderRepository.save(o1);
    

    付款不需要保存方法。因为您使用了@OneToOne(cascade=CascadeType.ALL, mappedBy="order") 之类的级联类型,所以每当您保存订单时,付款也会保存。

    【讨论】:

      【解决方案2】:

      因为我们必须像您使用的那样为父实体设置子实体 o1.setPayment(p1);

      不需要将 id 传递为 null,因为它将是 @GeneratedValue。您可能需要为它们创建一个合适的构造函数。

      当您使用cascade=CascadeType.ALL 时,您可以保存父母和孩子 如下 两个实体都不需要使用 save()

      //save Parent-Child at same 
              @PostMapping(value = "/onetoone")
              public String OneToOne(@RequestBody ParentOne parent)
              {
                  ChildOne childOne = parent.getChildOne();
                  childOne.setParentOne(parent);
                  parent.setChildOne(childOne);
                  parentOneRepository.save(parent);
                  return "saved";
      
                  /*{
                      "parentName":"Parent Name",
                      "childOne":{
                          "childName":"Child Name"
                      }
                  }*/
              }
      

      Discussion

      【讨论】:

        猜你喜欢
        • 2015-12-26
        • 1970-01-01
        • 2012-11-02
        • 2013-06-26
        • 2020-11-02
        相关资源
        最近更新 更多