JPA如何在从父级使用合并但是创建子级时获取生成的id /对象?

时间:2013-07-23 16:46:03

标签: java jpa

我有一个先前已经持久且与另一个实体有@OneToMany关系的实体。为了添加新实体,我只需在托管对象中添加新实体,并使用cascadeType.ALL来保留更改。有没有办法可以获取新创建的对象的id或获取我在合并中使用的原始(非托管)对象更新其ID?

在伪代码中,我希望会发生以下情况:

  1. 将为合并实体
  2. 返回新副本
  3. 旧副本将更新为新实体
  4. 实施例: 父A,id = 13 孩子B,id = 0

    本质上,我想在父级上发出merge但在子级上发布级联persist(以便更新原始子实例,而不是复制)。

    显然这不会发生。 我正在使用hibernate作为提供者。

4 个答案:

答案 0 :(得分:8)

Stackoverflow postJPA documentation会为您进行研究提供答案。

实现我想要的方法是在托管父级上使用persist。这将忽略父级的任何更改,但会级联persist(前提是它已设置为级联)。之后,子对象将具有正确的ID。

....
JPAEntity newObject=new JPAEntity();
managedObject.addChild(newObject);
em.persist(managedObject)
newObject.getId() //work fine!

答案 1 :(得分:1)

您应该能够“看到”新实体的生成ID:

    事务提交后
  • 在事务处于活动状态时em.flush()emEntityManager)之后

另请注意,实体之间的所有关系需要在持久性之前在Java数据结构中解析。对父母的子引用需要“设置”,反之亦然。

答案 2 :(得分:1)

我遇到了与持久性提供程序eclipselink类似的问题。我需要将具有临时“客户订单ID”的客户端数据库中的新订单添加到服务器数据库中的现有客户。因为我需要“服务器订单ID”用于进一步的客户端请求,我想创建一个映射(clientID,serverID)并将其发送回客户端。 基本上我的方法是获得对新添加的子订单副本的引用。它将始终添加到我的父类客户列表的末尾,该事实用于检索它。

我使用实体类Customer和Order,其中Customer有订单的List(LinkedList)。

父客户类:  ...

    @OneToMany(mappedBy = "customer", cascade=CascadeType.ALL, orphanRemoval = true)
    private List<Order> orders = new LinkedList<Order>();

    public Order getLastOrder() {
      return orders.get(orders.size()-1);
    }

Child Order课程:

    @ManyToOne(optional=false)
    private Customer customer;

的Servlet

    Customer customer = customerService.findByID(customerID); //existing customer
    Order order = new Order();
    //add attributes to new order
    customer.addOrder(order);
    customerService.update(customer); //generates keys for children
    order = customer.getLastOrder();
    Long orderID = order.getID; //Nullpointer exception

CustomerService使用EntityManager.merge更新客户,但我忘了更新servlet中的引用:

CustomerService类:

    public void update(Customer entity) {
      entityManager.merge(entity);
    }  

我这样解决了: CustomerService类:

    public Customer update(Customer entity) {
      return entityManager.merge(entity);
    }

的Servlet:   ....

    customer = customerService.update(customer); //generates keys for children

现在一切正常。

答案 3 :(得分:0)

确保在保留更改之前设置关系的两个站点。

child.setParent(parent);
parent.getChildren().add(child);
Parent parentWithId = em.merge(parent);
em.flush(); // make sure that the persistence context and database are in sync
parentWithId.getId(); // works
parentWithId.getChildren().get(0).getId(); // should also work