tutorial hibernate

hibernate tutorial



org.hibernate.PersistentObjectException: entidad separada pasada para persistir (3)

Había escrito con éxito mi primer ejemplo de hijo principal con Hibernate. Después de algunos días lo tomé de nuevo y actualicé algunas bibliotecas. No estoy seguro de lo que hice, pero nunca podría hacerlo funcionar nuevamente. ¿Alguien me ayudaría a descubrir qué está mal en el código que está devolviendo después del mensaje de error?

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)

mapeo de hibernación:

<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>

EDITAR: 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; } }

EDITAR: objeto JSON enviado desde el cliente:

{"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}]}

EDITAR: Algunos detalles:
Intenté guardar la factura siguiendo dos formas:

  1. Manufacturado manualmente el objeto json mencionado anteriormente y lo pasó a una nueva sesión del servidor. En este caso, no se ha realizado absolutamente ninguna actividad antes de llamar al método guardar, por lo que no debería haber ninguna sesión abierta, excepto la que se abrió en el método guardar.

  2. Los datos existentes cargados mediante el uso del método getInvoice y ellos pasaron los mismos datos después de eliminar el valor clave. Esto también creo que debería cerrar la sesión antes de guardar ya que la transacción se está cometiendo en el método getInvoice.

En ambos casos recibo el mismo mensaje de error que me obliga a creer que algo está mal con el archivo de configuración de hibernación o con las clases de entidades o con el método de guardar.

Por favor, avíseme si debería proporcionar más detalles


Aquí has ​​usado nativo y asignando valor a la clave principal, en la clave primaria nativa se genera automáticamente.

Por lo tanto, el problema está por venir.


Lo más probable es que el problema se encuentre fuera del código que nos está mostrando aquí. Está intentando actualizar un objeto que no está asociado con la sesión actual. Si no es la factura, entonces tal vez se trate de un elemento de factura que ya se ha conservado, obtenido de la base de datos, mantenido vivo en algún tipo de sesión y luego intenta persistir en una nueva sesión. Esto no es posible. Como regla general, nunca mantenga vivos sus objetos persistentes en todas las sesiones.

La solución será, por ejemplo, al obtener el gráfico de objeto completo de la misma sesión con la que intentas persistir. En un entorno web esto significaría:

  • Obtener la sesión
  • Obtenga los objetos que necesita para actualizar o agregar asociaciones. Preferable por su clave principal
  • Alterar lo que se necesita
  • Guardar / actualizar / desalojar / eliminar lo que quieras
  • Cerrar / comprometer su sesión / transacción

Si sigue teniendo problemas, publique algunos de los códigos que llaman a su servicio.


No proporcionó muchos detalles relevantes, así que supongo que llamó a getInvoice y luego utilizó el objeto de resultado para establecer algunos valores y llamar a save con la suposición de que los cambios de su objeto se guardarán.

Sin embargo, la operación persist está destinada a objetos transitorios completamente nuevos y falla si id ya está asignada. En su caso, es probable que desee llamar a saveOrUpdate lugar de persist .

Puede encontrar algunas discusiones y referencias aquí "entidad separada pasada para persistir el error" con código JPA / EJB