我有一个先前已经持久且与另一个实体有@OneToMany
关系的实体。为了添加新实体,我只需在托管对象中添加新实体,并使用cascadeType.ALL
来保留更改。有没有办法可以获取新创建的对象的id或获取我在合并中使用的原始(非托管)对象更新其ID?
在伪代码中,我希望会发生以下情况:
实施例: 父A,id = 13 孩子B,id = 0
本质上,我想在父级上发出merge
但在子级上发布级联persist
(以便更新原始子实例,而不是复制)。
显然这不会发生。 我正在使用hibernate作为提供者。
答案 0 :(得分:8)
Stackoverflow post和JPA documentation会为您进行研究提供答案。
实现我想要的方法是在托管父级上使用persist
。这将忽略父级的任何更改,但会级联persist
(前提是它已设置为级联)。之后,子对象将具有正确的ID。
....
JPAEntity newObject=new JPAEntity();
managedObject.addChild(newObject);
em.persist(managedObject)
newObject.getId() //work fine!
答案 1 :(得分:1)
您应该能够“看到”新实体的生成ID:
或
在事务处于活动状态时em.flush()
(em
为EntityManager
)之后
另请注意,实体之间的所有关系需要在持久性之前在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