getting result set into DTO with native SQL Query in Hibernate - java

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?

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 ;)
References
Hibernate Reference Guide
16.1.5. Returning non-managed entities
Hibernate's Blog
Hibernate 3.2: Transformers for HQL and SQL

Related

Converting SQL query with joins to JPA

I have this SQL query:
select ts.scorename from content_package cp
join content_package_content_package_components cpcps on cpcps.content_package = cp.id
join content_package_component cpc on cpc.id = cpcps.content_package_components
join tests t on t.id = cpc.assessment
join test_scores ts on ts.tests_id = t.id
where cp.tag = 'C_TS_EN_ABSA_G_'
And want to convert it to JPA, ideally Specifications - is this possible?
you can write this query in JPQL but firs you need to create POJO class of your models. if you are using Intelij idea you can create your models in it by going to persistence section ,right click on your data source and select generate persistence mapping by (hibernate or database schema). after creating models you should change your table names to pojo classes in query and so on ....

Complicated query with jparepository. Three tables join

I want to filter entities with next way:
get distinct 10 top disciplines, which are ordered by students count(attendance) for sessions between some period of time.
Discipline has List<Session> sessions;//bidirectional
Every Session has its own List<Student> students;//bidirectional
So, Student didn't know anything about Discipline, only via Session.
And I want to write using Spring JpaRepository something like:
List<Discipline> findTop10DisciplinesDistinctOrderBySessionsStudentsCountAndBySessionsBetween(Date from, Date to);
but there are some restrictions. It didn't work for me
No property count found for type Student! Traversed path:
Discipline.sessions.students.
Query looks like this(mysql):
select d.*
from session as ses
inner join
(select st.*
from student as st
inner join session as ses on ses.id = st.session_id
where ses.time > (curdate() - interval 30 day)
group by st.session_id
order by count(st.id) desc
limit 10) as st2
on ses.id = st2.session_id
inner join discipline as d on ses.discipline_id = d.id
But how to add this query to jpa repository?
Derived queries, those that get created from the method name are not suitable for use cases as yours. Even if it would work it would result in an unwieldy method name. Use an #Query with JPQL or SQL query instead.

Spring data jpa from multiple tables

I am using spring data jpa. And I have a inner join on two tables. This is my query.
SELECT A.NAME, A.CARD_NUMBER, A.ADDRESS, A.EMAIL FROM USER_INFO ABC INNER JOIN USR_DETAIL DEF ON (ABC.ID = DEF.ID) WHERE ABC.ID = '123456';
The two table here have no relationship. So one-to-one or many-to-one or many-to-many on the column name doesn't make sense. Can I define entities without relationship? The reason why we are doing a inner join on the two tables here is simply because doing a join on both of them will be a expensive query.
You can define both entities without any kind of relationship and then you can retrieve the data specifying nativeQuery=true in the #Query(..) annotation in the read method.
#Query(value = "SELECT ABC.NAME, ABC.CARD_NUMBER, ABC.ADDRESS, ABC.EMAIL " +
"FROM USER_INFO ABC " +
"INNER JOIN USR_DETAIL DEF ON (ABC.ID = DEF.ID) " +
"WHERE ABC.ID = :id", nativeQuery = true)
UserInfoDetails retrieveUserInfoAndDetailById(#Param("id") String id);
Side notes:
In the projection of the query, I correct the alias from A to ABC as the query was not written correctly. Feel free to edit the projection accordingly to your needs.
As a return type, I wrote a UserInfoDetails class, supposing it will be return something similar. Feel free to change it accordingly to your needs.

Spring : JPA to convert native SQL to non entity pojo

I have native SQL which returns the collection of objects and i would like to get the results as collection of objects(a pojo class which is non entity)
is it possible to get the results from native SQL as collection of non entity?
I am using spring jpa 1.10
There is no way to mapping non-entity classes in JPA 1.
Since JPA 2.1, you can use ConstructorResult, Used in conjunction with the SqlResultSetMapping annotation to map the SELECT clause of a SQL query to a constructor.
Here is the example
Query q = em.createNativeQuery(
"SELECT c.id, c.name, COUNT(o) as orderCount, AVG(o.price) AS avgOrder " +
"FROM Customer c, Orders o " +
"WHERE o.cid = c.id " +
"GROUP BY c.id, c.name",
"CustomerDetailsResult");
#SqlResultSetMapping(
name="CustomerDetailsResult",
classes={
#ConstructorResult(
targetClass=com.acme.CustomerDetails.class,
columns={
#ColumnResult(name="id"),
#ColumnResult(name="name"),
#ColumnResult(name="orderCount"),
#ColumnResult(name="avgOrder", type=Double.class)
}
)
}
)
Mapping NativeQuery results into a POJO - this is JPA independent solution using #JsonFormat and ObjectMapper, detailed with code sample to what #darshan-patel already mentioned.

Join in #NamedQuery: Unexpected token ON

In Hibernate, I created a query using JOIN to join two tables. The query executes fine in Oracles SQL Developer. However, if I add it to a #NamedQuery, the server starts with this error:
Error in named query: loadFooByAnother: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ON near line 1, column xxx
My named query is:
SELECT foo FROM FooTable foo JOIN BarTable bar
ON foo.something=bar.somethingId
WHERE bar.anotherId=:another
Is it not possible to use JOIN .. ON syntax in Hibernate?
You need to use the with directive, if you use HQL:
SELECT foo
FROM FooEntity foo
JOIN foo.bar b with b.name = :name
WHERE foo.prop = :prop
This is for supplying a custom ON clause. From your example, judging from how you joined tables, I think you tried to execute a native SQL using a #NamedQuery.
If you want to run a native SQL query, you have to use #NamedNativeQuery instead.
If you want to use HQL, you need to use Entities and to join Entity associations (not tables).
If you use JPQL then the with directive has to be replaced by the on directive, but again, you need to navigate entity associations, meaning you have to map them first.

Categories

Resources