Saltar al contenido

Asignación de consulta de proyección JPA o Hibernate a DTO (objeto de transferencia de datos)

Agradeceríamos tu ayuda para compartir nuestras crónicas con relación a las ciencias informáticas.

Solución:

Tiene tantas opciones para mapear su proyección a un conjunto de resultados DTO:

Proyecciones DTO usando Tuple y JPQL

List postDTOs = entityManager.createQuery("""
    select
           p.id as id,
           p.title as title
    from Post p
    where p.createdOn > :fromTimestamp
    """, Tuple.class)
.setParameter( "fromTimestamp", Timestamp.from(
    LocalDateTime.of(2016, 1, 1, 0, 0, 0)
        .toInstant(ZoneOffset.UTC )))
.getResultList();

assertFalse(postDTOs.isEmpty());
 
Tuple postDTO = postDTOs.get(0);
assertEquals( 
    1L, 
    postDTO.get("id") 
);

Proyecciones DTO utilizando una expresión de constructor y JPQL

List postDTOs = entityManager.createQuery("""
    select new com.vladmihalcea.book.hpjp.hibernate.query.dto.projection.jpa.PostDTO(
        p.id,
        p.title
    )
    from Post p
    where p.createdOn > :fromTimestamp
    """, PostDTO.class)
.setParameter( "fromTimestamp", Timestamp.from(
    LocalDateTime.of( 2016, 1, 1, 0, 0, 0 )
        .toInstant( ZoneOffset.UTC ) ))
.getResultList();

También puede omitir el nombre del paquete DTO de la expresión del constructor JPA y hacer referencia al DTO por su nombre de clase Java simple (p. ej., PostDTO).

List postDTOs = entityManager.createQuery("""
    select new PostDTO(
        p.id,
        p.title
    )
    from Post p
    where p.createdOn > :fromTimestamp
      """, PostDTO.class)
.setParameter( "fromTimestamp", Timestamp.from(
  LocalDateTime.of( 2016, 1, 1, 0, 0, 0 )
      .toInstant( ZoneOffset.UTC ) ))
.getResultList();

Proyecciones DTO utilizando Tuple y consultas SQL nativas

Este está disponible en Hibernate 5.2.11, así que una razón más para actualizar.

List postDTOs = entityManager.createNativeQuery("""
    SELECT
           p.id AS id,
           p.title AS title
    FROM Post p
    WHERE p.created_on > :fromTimestamp
    """, Tuple.class)
.setParameter( "fromTimestamp", Timestamp.from(
    LocalDateTime.of( 2016, 1, 1, 0, 0, 0 )
        .toInstant( ZoneOffset.UTC ) ))
.getResultList();

Proyecciones DTO utilizando un ConstructorResult

Si usamos el mismo PostDTO tipo de clase introducido anteriormente, tenemos que proporcionar lo siguiente @SqlResultSetMapping:

@NamedNativeQuery(
    name = "PostDTO",
    query = """
        SELECT
               p.id AS id,
               p.title AS title
        FROM Post p
        WHERE p.created_on > :fromTimestamp
        """,
    resultSetMapping = "PostDTO"
)
@SqlResultSetMapping(
    name = "PostDTO",
    classes = @ConstructorResult(
        targetClass = PostDTO.class,
        columns = 
            @ColumnResult(name = "id"),
            @ColumnResult(name = "title")
        
    )
)

Ahora, la proyección de SQL denominada consulta nativa se ejecuta de la siguiente manera:

List postDTOs = entityManager.createNamedQuery("PostDTO")
.setParameter( "fromTimestamp", Timestamp.from(
    LocalDateTime.of( 2016, 1, 1, 0, 0, 0 )
        .toInstant( ZoneOffset.UTC ) ))
.getResultList();

Proyecciones DTO usando ResultTransformer y JPQL

Esta vez, su DTO requiere tener los configuradores de las propiedades que necesita que Hibernate complete desde el JDBC subyacente. ResultSet.

La proyección DTO tiene el siguiente aspecto:

List postDTOs = entityManager.createQuery("""
    select
           p.id as id,
           p.title as title
    from Post p
    where p.createdOn > :fromTimestamp
    """)
.setParameter( "fromTimestamp", Timestamp.from(
    LocalDateTime.of( 2016, 1, 1, 0, 0, 0 ).toInstant( ZoneOffset.UTC ) ))
.unwrap( org.hibernate.query.Query.class )
.setResultTransformer( Transformers.aliasToBean( PostDTO.class ) )
.getResultList();

Proyecciones DTO utilizando ResultTransformer y una consulta SQL nativa

List postDTOs = entityManager.createNativeQuery("""
    select
           p.id as "id",
           p.title as "title"
    from Post p
    where p.created_on > :fromTimestamp
    """)
.setParameter( "fromTimestamp", Timestamp.from(
    LocalDateTime.of( 2016, 1, 1, 0, 0, 0 ).toInstant( ZoneOffset.UTC ) ))
.unwrap( org.hibernate.query.NativeQuery.class )
.setResultTransformer( Transformers.aliasToBean( PostDTO.class ) )
.getResultList();

Puede usar ResultTransformer, que puede convertir propiedades de alias a bean (DTO). Para su uso, puede consultar los documentos de Hibernate aquí en la sección 13.1.5

Si sostienes algún recelo y disposición de avanzar nuestro sección eres capaz de realizar una anotación y con gusto lo analizaremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *