listar insertar example entitymanagerfactory ejemplo datos context consultas con jpa persistence thread-safety dao fetching-strategy

insertar - listar con jpa



¿Hay una manera de cambiar el tipo de recuperación JPA en un método? (4)

Como nadie mencionó OpenJPA, pondré una respuesta aquí.

En OpenJPA, las colecciones y campos configurados de forma perezosa anteriormente se pueden cargar con entusiasmo como se muestra a continuación

OpenJPAEntityManager kem = OpenJPAPersistence.cast(em); kem.getFetchPlan().addField(Order.class, "products"); TypedQuery<Order> query = kem.createQuery(yourQuery, Order.class);

Referencia: http://openjpa.apache.org/builds/1.0.3/apache-openjpa-1.0.3/docs/manual/ref_guide_fetch.html

¿Hay una manera de cambiar el tipo de recuperación JPA en un solo método sin editar el objeto de entidad?

Tengo una capa ORM compartida que consta de clases de entidad JPA. A esta capa ORM se accede mediante dos capas DAO. Una DAO necesita recuperación perezosa, como lo es para mi aplicación web, la otra necesita recuperación, ya que necesito que sea segura para subprocesos.

Aquí hay un método de ejemplo de mi DAO threadsafe,

@PersistenceContext(unitName = "PersistenceUnit", type = PersistenceContextType.TRANSACTION) private EntityManager em; public ErrorCode findErrorCodeById(short id) { return (ErrorCode) em.createNamedQuery("ErrorCode.findById"). setParameter("id", id).getSingleResult(); }

¿Cómo puedo hacer que este método (o toda la clase) use la búsqueda ansiosa?


En JPA, el modo de recuperación se especifica en cada atributo de persistencia, ya sea a través de una anotación o en un archivo de mapeo xml.

Por lo tanto, una forma independiente de un proveedor de JPA para lograr su objetivo es tener un archivo de mapeo separado para cada capa DAO. Desafortunadamente, esto requerirá una PersistenceUnit separada para cada archivo de mapeo, pero al menos puede compartir las mismas clases de entidad y la misma consulta de JPQL.

Los esqueletos de código siguen.

persistence.xml:

<persistence> <persistence-unit name="dao-eager"> <mapping-file>orm-eager.xml</mapping-file> </persistence-unit> <persistence-unit name="dao-lazy"> <mapping-file>orm-lazy.xml</mapping-file> </persistence-unit> </persistence>

orm-eager.xml:

<entity-mappings> <entity class="ErrorCode"> <attributes> <basic name="name" fetch="EAGER"/> </attributes> </entity> </entity-mappings>

orm-lazy.xml:

<entity-mappings> <entity class="ErrorCode"> <attributes> <basic name="name" fetch="LAZY"/> </attributes> </entity> </entity-mappings>

Entonces solo es cuestión de crear un EntityManagerFactory para la unidad de persistencia adecuada en sus capas DAO.

En realidad, no necesita dos archivos de mapeo, puede especificar LAZY o EAGER como una anotación en la Entidad y luego especificar el opuesto en un archivo de mapeo xml (aún así querrá dos unidades de persistencia).

Puede ser un poco más de código que la solución de Hibernate anterior, pero su aplicación debería ser portátil a otros proveedores de JPA.

Además, OpenJPA proporciona una funcionalidad similar a la solución de Hibernate anterior al usar FetchGroups (un concepto tomado de JDO).

Una última advertencia, FetchType.LAZY es una sugerencia en JPA, el proveedor puede cargar las filas con entusiasmo si es necesario.

Actualizado por solicitud.

Considera una entidad como esta:

@Entity public class ErrorCode { // . . . @OneToMany(fetch=FetchType.EAGER) // default fetch is LAZY for Collections private Collection myCollection; // . . . }

En ese caso, aún necesitaría dos unidades de persistencia, pero solo necesitará orm-lazy.xml. Cambié el nombre del campo para reflejar un escenario más realista (solo las colecciones y los blobs usan FetchType.LAZY de forma predeterminada). Por lo tanto, el orm-lazy.xml resultante podría tener este aspecto:

<entity-mappings> <entity class="ErrorCode"> <attributes> <one-to-many name="myCollection" fetch="LAZY"/> </attributes> </entity> </entity-mappings>

Y persistence.xml se verá así:

<persistence> <persistence-unit name="dao-eager"> <!-- . . . --> </persistence-unit> <persistence-unit name="dao-lazy"> <!-- . . . --> <mapping-file>orm-lazy.xml</mapping-file> </persistence-unit> </persistence>


Supongo que sus asociaciones de entidades (@OneToOne, @OneToMany, @ManyToOne) se han convertido en perezosas (FetchType.Lazy)

Entonces puedo pensar en dos maneras:

A. escriba dos consultas jpa, una que busque la asociación de la perezosa (esa es la forma predeterminada de hibernación) y una segunda consulta que obliga explícitamente a cargar la asociación (consulte la palabra clave "buscar" en la consulta).

Query q = HibernateUtil.getSessionFactory().getCurrentSession() .createQuery("select c from Category as c" + " left join fetch c.categorizedItems as ci" + " join fetch ci.item as i");

B. use Hibernate.initialize (entidad) para forzar la carga impaciente de relaciones perezosas de una entidad después de que la haya recuperado (por ejemplo, a través del buscador ...)

ErrorCode lazyCode = findErrorCodeById(1); // eager load associations Hibernate.initialize(lazyCode);


En JPA2 , uso EntityGraphs , que le permite definir qué entidades relacionadas desea recuperar:

https://docs.oracle.com/javaee/7/tutorial/persistence-entitygraphs002.htm https://docs.oracle.com/javaee/7/tutorial/persistence-entitygraphs003.htm

Crea una NamedQuery como lo hizo y adjunta una sugerencia con la clave javax.persistence.loadgraph o javax.persistence.fetchgraph . Recuperará las entidades relacionadas que definió en el gráfico.

Puede encontrar los detalles de la diferencia entre "loadgraph" y "fetchgraph" aquí: ¿Cuál es la diferencia entre FETCH y LOAD para el gráfico de entidad de JPA?