tutorial example espaƱol ejemplo crear buscar java orm jpa

example - jpa java se



Separar una entidad del contexto de persistencia JPA/EJB3 (14)

(puede ser demasiado tarde para responder, pero puede ser útil para otros)

Estoy desarrollando mi primer sistema con JPA ahora mismo. Lamentablemente, me enfrento a este problema cuando este sistema está casi completo.

Simplemente pon. Use Hibernate o espere a JPA 2.0.

En Hibernate, puede usar ''session.evict (object)'' para eliminar un objeto de la sesión. En JPA 2.0, en borrador en este momento , existe el método ''EntityManager.detach (object)'' para separar un objeto del contexto de persistencia.

¿Cuál sería la forma más fácil de separar un Bean de entidad JPA específico que se adquirió a través de un EntityManager? Alternativamente, ¿podría hacer que una consulta devuelva objetos separados en primer lugar para que esencialmente actúen como "solo lectura"?

La razón por la que quiero hacer esto es porque quiero modificar los datos dentro del bean, solo en mi aplicación, pero nunca la he conservado en la base de datos. En mi programa, finalmente tengo que llamar a flush () en EntityManager, que persistiría todos los cambios de las entidades adjuntas a la base de datos subyacente, pero quiero excluir objetos específicos.


Creo que también puede usar el método EntityManager.refresh (Object o) si la clave principal de la entidad no se ha modificado. Este método restaurará el estado original de la entidad.


Dado que estoy usando SEAM y JPA 1.0 y mi sistema tiene una fuctinalidad que necesita registrar todos los cambios en los campos, he creado un objeto de valor o un objeto de transferencia de datos si los mismos campos de la entidad que se deben registrar. El constructor del nuevo pojo es:

public DocumentoAntigoDTO(Documento documentoAtual) { Method[] metodosDocumento = Documento.class.getMethods(); for(Method metodo:metodosDocumento){ if(metodo.getName().contains("get")){ try { Object resultadoInvoke = metodo.invoke(documentoAtual,null); Method[] metodosDocumentoAntigo = DocumentoAntigoDTO.class.getMethods(); for(Method metodoAntigo : metodosDocumentoAntigo){ String metodSetName = "set" + metodo.getName().substring(3); if(metodoAntigo.getName().equals(metodSetName)){ metodoAntigo.invoke(this, resultadoInvoke); } } } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } }


Desafortunadamente, no hay forma de desconectar un objeto del administrador de entidades en la implementación actual de JPA, AFAIR.

EntityManager.clear () desconectará todos los objetos JPA, por lo que podría no ser una solución adecuada en todos los casos, si tiene otros objetos que planea mantener conectados.

Entonces, su mejor opción sería clonar los objetos y pasar los clones al código que cambia los objetos. Como los campos de objetos primitivos e inmutables son atendidos por el mecanismo de clonación predeterminado de una manera adecuada, no tendrá que escribir mucho código de plomería (aparte de la clonación profunda de cualquier estructura agregada que pueda tener).


En JPA 1.0 (probado usando EclipseLink) puede recuperar la entidad fuera de una transacción. Por ejemplo, con las transacciones administradas por contenedor, usted podría hacer:

public MyEntity myMethod(long id) { final MyEntity myEntity = retrieve(id); // myEntity is detached here } @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public MyEntity retrieve(long id) { return entityManager.find(MyEntity.class, id); }


Hasta donde yo sé, las únicas formas directas de hacerlo son:

  1. Confirme el txn - Probablemente no sea una opción razonable
  2. Borre el contexto de persistencia - EntityManager.clear () - Esto es brutal, pero lo eliminaría
  3. Copie el objeto: la mayoría de las veces sus objetos JPA son serializables, por lo que esto debería ser fácil (si no particularmente eficiente).

Mauricio Kanada, gracias por este consejo, el método evict () funciona bien. Utilizo JPA de SEAM, existe un soporte integrado de JPA Entity Manager, y es posible acceder a la sesión de Hibernate Delegate y, por lo tanto, este método "expulsa".

Muchas gracias, Zmicer


Si llegas aquí porque realmente quieres pasar una entidad a través de un límite remoto, entonces simplemente pones un código para engañar al hibernazi.

for(RssItem i : result.getChannel().getItem()){ }

Cloneable no funcionará porque en realidad copia PersistantBag.

Y olvídate de usar streams serializables y bytearray y streams canalizados. crear hilos para evitar interbloqueos mata todo el concepto.


Si necesita separar un objeto de EntityManager y está utilizando Hibernate como capa subyacente de ORM, puede obtener acceso al objeto Session de Hibernate y usar el método Session.evict(Object) que Mauricio Kanada mencionó anteriormente.

public void detach(Object entity) { org.hibernate.Session session = (Session) entityManager.getDelegate(); session.evict(entity); }

Por supuesto, esto se rompería si cambias a otro proveedor de ORM pero creo que esto es preferible para tratar de hacer una copia profunda.


Si no hay demasiadas propiedades en el bean, puede crear una nueva instancia y establecer todas sus propiedades manualmente desde el bean persistente.

Esto podría implementarse como un constructor de copia, por ejemplo:

public Thing(Thing oldBean) { this.setPropertyOne(oldBean.getPropertyOne()); // and so on }

Entonces:

Thing newBean = new Thing(oldBean);


Si usa EclipseLink , también tiene las opciones,

Utilice la sugerencia de consulta, eclipselink.maintain-cache"="false : todos los objetos devueltos se separarán.

Use la JpaEntityManager EclipseLink JpaEntityManager copy() para copiar el objeto a la profundidad deseada.


Tratar con un caso similar He creado un objeto DTO que amplía el objeto persistente de la entidad de la siguiente manera:

class MyEntity { public static class MyEntityDO extends MyEntity {} }

Finalmente, una consulta escalar recuperará los atributos no gestionados deseados:

(Hibernate) select p.id, p.name from MyEntity P (JPA) select new MyEntity(p.id, p.name) from myEntity P


esto es rápido y sucio, pero también puedes serializar y deserializar el objeto.


No importa qué implementación de JPA utilice, solo use entityManager.detach(object) ahora está en JPA 2.0 y parte de JEE6.