org.hibernate.PersistentObjectException:传递给persist的分离实体
我已经成功地用hibernate写了我的第一个主子例子。 几天后,我又拿了一次,升级了一些图书馆。 不知道我做了什么,但我永远不能让它再次运行。 有人会帮我找出错误信息返回的代码中出了什么问题:
org.hibernate.PersistentObjectException: detached entity passed to persist: example.forms.InvoiceItem at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:127) at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:799) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:791) .... (truncated)
hibernate映射:
<hibernate-mapping package="example.forms"> <class name="Invoice" table="Invoices"> <id name="id" type="long"> <generator class="native" /> </id> <property name="invDate" type="timestamp" /> <property name="customerId" type="int" /> <set cascade="all" inverse="true" lazy="true" name="items" order-by="id"> <key column="invoiceId" /> <one-to-many class="InvoiceItem" /> </set> </class> <class name="InvoiceItem" table="InvoiceItems"> <id column="id" name="itemId" type="long"> <generator class="native" /> </id> <property name="productId" type="long" /> <property name="packname" type="string" /> <property name="quantity" type="int" /> <property name="price" type="double" /> <many-to-one class="example.forms.Invoice" column="invoiceId" name="invoice" not-null="true" /> </class> </hibernate-mapping>
编辑: InvoiceManager.java
class InvoiceManager { public Long save(Invoice theInvoice) throws RemoteException { Session session = HbmUtils.getSessionFactory().getCurrentSession(); Transaction tx = null; Long id = null; try { tx = session.beginTransaction(); session.persist(theInvoice); tx.commit(); id = theInvoice.getId(); } catch (RuntimeException e) { if (tx != null) tx.rollback(); e.printStackTrace(); throw new RemoteException("Invoice could not be saved"); } finally { if (session.isOpen()) session.close(); } return id; } public Invoice getInvoice(Long cid) throws RemoteException { Session session = HbmUtils.getSessionFactory().getCurrentSession(); Transaction tx = null; Invoice theInvoice = null; try { tx = session.beginTransaction(); Query q = session .createQuery( "from Invoice as invoice " + "left join fetch invoice.items as invoiceItems " + "where invoice.id = :id ") .setReadOnly(true); q.setParameter("id", cid); theInvoice = (Invoice) q.uniqueResult(); tx.commit(); } catch (RuntimeException e) { tx.rollback(); } finally { if (session.isOpen()) session.close(); } return theInvoice; } }
Invoice.java
public class Invoice implements java.io.Serializable { private Long id; private Date invDate; private int customerId; private Set<InvoiceItem> items; public Long getId() { return id; } public Date getInvDate() { return invDate; } public int getCustomerId() { return customerId; } public Set<InvoiceItem> getItems() { return items; } void setId(Long id) { this.id = id; } void setInvDate(Date invDate) { this.invDate = invDate; } void setCustomerId(int customerId) { this.customerId = customerId; } void setItems(Set<InvoiceItem> items) { this.items = items; } }
InvoiceItem.java
public class InvoiceItem implements java.io.Serializable { private Long itemId; private long productId; private String packname; private int quantity; private double price; private Invoice invoice; public Long getItemId() { return itemId; } public long getProductId() { return productId; } public String getPackname() { return packname; } public int getQuantity() { return quantity; } public double getPrice() { return price; } public Invoice getInvoice() { return invoice; } void setItemId(Long itemId) { this.itemId = itemId; } void setProductId(long productId) { this.productId = productId; } void setPackname(String packname) { this.packname = packname; } void setQuantity(int quantity) { this.quantity = quantity; } void setPrice(double price) { this.price = price; } void setInvoice(Invoice invoice) { this.invoice = invoice; } }
编辑:从客户端发送的JSON对象:
{"id":null,"customerId":3,"invDate":"2005-06-07T04:00:00.000Z","items":[ {"itemId":1,"productId":1,"quantity":10,"price":100}, {"itemId":2,"productId":2,"quantity":20,"price":200}, {"itemId":3,"productId":3,"quantity":30,"price":300}]}
编辑:一些细节:
我试图通过以下两种方式来保存发票:
-
手动制作上面提到的json对象,并将其传递给服务器的新会话。 在这种情况下,在调用save方法之前绝对没有任何活动,所以除了在save方法中打开的那个之外,不应该有任何打开的会话
-
使用getInvoice方法加载现有数据,并在删除键值后传递相同的数据。 这也是我相信应该closures会话保存之前,因为事务提交在getInvoice方法。
在这两种情况下,我得到相同的错误消息,迫使我相信,有些东西是错误的,无论是configuration文件或实体类或保存方法。
请让我知道,如果我应该提供更多的细节
你没有提供很多相关的细节,所以我猜测你调用了getInvoice
,然后你使用了result对象来设置一些值,并save
并假定你的对象更改将被保存。
但是, persist
操作用于全新的瞬态对象,如果已经分配了id,则操作失败。 在你的情况下,你可能想调用saveOrUpdate
而不是persist
。
您可以在这里find一些讨论和参考“使用JPA / EJB代码传递给持久错误的分离实体”
在这里你已经使用了native和赋值给主键,在本地主键是自动生成的。
因此,问题即将到来。
这个问题很可能在您向我们展示的代码之外。 您正尝试更新与当前会话不相关的对象。 如果它不是发票,那么也许它是一个InvoiceItem已经被持续,从数据库中获得,保持在某种forms的会议,然后你试图坚持在一个新的会议。 这不可能。 一般来说,永远不要让持久对象在会话中保持活动状态。
该解决scheme将在即将获得整个对象graphics,从同一个会话你试图坚持下去。 在networking环境中,这意味着:
- 获得会议
- 获取您需要更新或添加关联的对象。 最好由他们的主要关键
- 改变需要什么
- 保存/更新/驱逐/删除你想要的
- closures/提交你的会话/交易
如果您不断有问题发布一些调用您的服务的代码。