Using:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.5.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>1.5.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>1.5.8.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
this is my DTO. It is not an Entity on DB. I want to use it only for mapping
public class PoolStateResult {
private Integer totalCodes;
private Integer assignedCodes;
private Integer availableCodes;
private Date startDateValidate;
private Date endDateValidate;
constructors
getters and setters
this is the content of DAO
Query q = em.createNativeQuery(" SELECT p.start_validity_date as startDateValidate, "
+ " p.end_validity_date as endDateValidate, "
+ " (SELECT count(*) from POOL_CODES p WHERE p.id_pool = :poolCode) as totalCodes, "
+ " (SELECT count(*) "
+ " from VOUCHER v "
+ " WHERE v.id_reference_pool = :poolCode "
+ " AND v.status = 'ASSEGNATO') as assignedCodes, "
+ " (SELECT count(*) "
+ " from VOUCHER v, POOL_CODES p "
+ " WHERE v.id_reference_pool = p.id_pool "
+ " AND v.id_reference_pool = :poolCode "
+ " AND v.status = 'ASSEGNATO' "
+ " and p.end_validity_date < sysdate) as availableCodes "
+ " from POOL_CODES p "
+ " WHERE p.id_pool = :poolCode",PoolStateResult.class);
q.setParameter("poolCode", "poolCode");
return (PoolStateResult) q.getSingleResult();
I add this package in configuration class
entityManagerFactory.setPackagesToScan(
env.getProperty("entitymanager.packages.to.scan"),
this is the exception
javax.persistence.NoResultException: No entity found for query
at org.hibernate.jpa.internal.QueryImpl.getSingleResult(QueryImpl.java:532)
Is there a way to force the mapping automatically as for all entity tables or the only way, with hibernate, for these types of queries is writing the mapping? Is this the best and only way to map a non-entity Java object using Hibernate?
@SqlResultSetMapping(
name="getPoolStateResult",
classes={
@ConstructorResult(
targetClass=PoolStateResult.class,
columns={
@ColumnResult(name="totalCodes", type=Integer.class),
@ColumnResult(name="assignedCodes", type=Integer.class),
@ColumnResult(name="availableCodes", type=Integer.class),
@ColumnResult(name="startDateValidate", type=Date.class),
@ColumnResult(name="endValidityDate", type=Date.class)
}
)
}
)
Then, where would the advantages of hibernate in this case?
Thanks
No JPA and Hibernate can't automatically map a query result to a DTO without any mapping information. You either map the result programmatically or you define a constructor call in an @SqlResultSetMapping
, as you did in your example.
You don't need to do that if you want to map the result to an entity. Hibernate then tries to use the mapping definition of the entity to map the query result. So, your query result needs to return all entity attributes and they have to have the same name as you use in your entity mapping. I explained that in more details in a series of blog posts about @SqlResultMapping
.
Regarding the benefits of using Hibernate for such a query: Hibernate doesn't provide you any benefits if this is the only database interaction you perform in a transaction. But it allows you to use this query within a Hibernate session and therefore within the same transaction as all other operations Hibernate performs in that session.