I have a query like below
select f.id, s.name, ss.name from first f left join second s on f.id = s.id left join second ss on f.sId = ss.id
If I could use HQL, I would have used HQL constructor syntax to directly populate DTO with the result set. But, since hibernate doesn't allow left join without having an association in place I have to use the Native SQL Query.
Currently I am looping through the result set in JDBC style and populating DTO objects. Is there any simpler way to achieve it?
Interface-based DTO projections You first need to define an interface that defines a getter method for each attribute your projection shall contain. At runtime, Spring Data JPA then generates a class that implements that interface. you can then use that interface as the return type of a repository method.
Hibernate provide option to execute native SQL queries through the use of SQLQuery object. Hibernate SQL Query is very handy when we have to execute database vendor specific queries that are not supported by Hibernate API.
The easiest way to map a query result to an entity is to provide the entity class as a parameter to the createNativeQuery(String sqlString, Class resultClass) method of the EntityManager and use the default mapping.
We can use @Query annotation to specify a query within a repository. Following is an example. In this example, we are using native query, and set an attribute nativeQuery=true in Query annotation to mark the query as native. We've added custom methods in Repository in JPA Custom Query chapter.
You could maybe use a result transformer. Quoting Hibernate 3.2: Transformers for HQL and SQL:
SQL Transformers
With native sql returning non-entity beans or Map's is often more useful instead of basic
Object[]
. With result transformers that is now possible.List resultWithAliasedBean = s.createSQLQuery( "SELECT st.name as studentName, co.description as courseDescription " + "FROM Enrolment e " + "INNER JOIN Student st on e.studentId=st.studentId " + "INNER JOIN Course co on e.courseCode=co.courseCode") .addScalar("studentName") .addScalar("courseDescription") .setResultTransformer( Transformers.aliasToBean(StudentDTO.class)) .list(); StudentDTO dto =(StudentDTO) resultWithAliasedBean.get(0);
Tip: the
addScalar()
calls were required on HSQLDB to make it match a property name since it returns column names in all uppercase (e.g. "STUDENTNAME"). This could also be solved with a custom transformer that search the property names instead of using exact match - maybe we should provide a fuzzyAliasToBean() method ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With