Is JPQL not the way to go for projections? - java

Here's my Repository method that I'm trying to call.
#Query(value = "select ise from InquirySession ise " +
"inner join ise.inquiryRequest.inquiryRequestFacilities irf " +
"left outer join ise.inquiryResponses ire on ire.facilityId = ?2 " +
"left outer join ire.responseActions ira " +
"left outer join ire.acceptDates irad " +
"left outer join ire.responseReasons irr " +
"where ise.carePathItem.id = ?1 and irf.facilityId = ?2")
Set<InquirySession> getAllByCarePathItemIdAndProviderId(final Long carePathItemId, final Long providerId);
My thought process was that when this method is executed, ise.inquiryResponses would be joined to InquirySession using the additional 'on' clause defined in the JPQL. However, I think this JPQL only selects InquirySession and does separate calls to join all other entities (defined in InquirySession) as I see separate sql statements after this one joining each entity using the primary/foreign key relationship.
Here's how InquiryResponse looks inside InquirySession
#OneToMany(mappedBy = "inquirySessionId")
#OrderBy(value = "createDate")
private Set<InquiryResponse> inquiryResponses;
and vice versa,
#Column(name = "inquirySessionDatabaseKey")
private Long inquirySessionId;
Is it possible to join InquiryResponse with the additional on clause ire.facilityId = ?2 when hydrating InquirySession entity using JPQL?
Edit
JPQL equivalent SQL
select inquiryses0_.inquirySessionId as inquirySessionId1_36_, inquiryses0_.carepathitemid as CarePat12_36_, inquiryses0_.createDate as createDa2_36_, inquiryses0_.description as descript3_36_,
inquiryses0_.fileSize as fileSize4_36_, inquiryses0_.documentLink as inquiryS5_36_, inquiryses0_.numberOfPages as numberOf6_36_, inquiryses0_.patientId as patientId7_36_,
inquiryses0_.patientEncounterId as patientV8_36_, inquiryses0_.patientplannerid as patientplannerid13_36_, inquiryses0_.purgedOn as purgedOn9_36_, inquiryses0_.amazonbucketname as s10_36_,
inquiryses0_.type as type11_36_
from InquirySession inquiryses0_
inner join InquiryRequest inquiryreq1_ on inquiryses0_.inquirySessionId=inquiryreq1_.inquirySessionId
inner join InquiryRequest_Facility inquiryreq2_ on inquiryreq1_.inquiryrequestid=inquiryreq2_.inquiryrequestid
left outer join InquiryResponse inquiryres3_ on inquiryses0_.inquirySessionId=inquiryres3_.inquirySessionId and (inquiryres3_.providerId=?)
left outer join InquiryResponse_Action_Link inquiryres3_1_ on inquiryres3_.inquiryresponseid=inquiryres3_1_.inquiryresponseid
left outer join InquiryResponseActions inquiryres4_ on inquiryres3_1_.inquiryresponseactionid=inquiryres4_.inquiryresponseactionid
left outer join InquiryResponse_AcceptDate_Link acceptdate5_ on inquiryres3_.inquiryresponseid=acceptdate5_.inquiryresponseid
left outer join InquiryResponse_Reason_Link responsere6_ on inquiryres3_.inquiryresponseid=responsere6_.inquiryresponseid
left outer join InquiryResponseReasons inquiryres7_ on responsere6_.responsereasonid=inquiryres7_.responsereasonid
where inquiryses0_.carepathitemid=? and inquiryreq2_.providerId=?
SQL that does not honor the 'on' clause and joins just on InquirySession.inquirySessionId
select inquiryres0_.inquirySessionId as inquirySessionId5_30_0_, inquiryres0_.inquiryresponseid as inquiryresponseid1_30_0_, inquiryres0_.inquiryresponseid as inquiryresponseid1_30_1_, inquiryres0_.createDate as createDa2_30_1_,
inquiryres0_.providerId as providerId3_30_1_, inquiryres0_.alsoCallMe as alsoCall4_30_1_, inquiryres0_.inquirySessionId as inquirySessionId5_30_1_, inquiryres0_.phoneNumber as phoneNum6_30_1_,
inquiryres0_.respondedBy as responde7_30_1_, inquiryres0_.responseText as response8_30_1_, inquiryres0_.responseTypeID as response9_30_1_,
inquiryres0_1_.inquiryresponseactionid as RSPNS_AC1_32_1_, inquiryres1_.inquiryresponseactionid as RSPNS_AC1_34_2_, inquiryres1_.inquiryresponseactiondescription as RSPNS_AC2_34_2_
from InquiryResponse inquiryres0_
left outer join InquiryResponse_Action_Link inquiryres0_1_ on inquiryres0_.inquiryresponseid=inquiryres0_1_.inquiryresponseid
inner join InquiryResponseActions inquiryres1_ on inquiryres0_1_.inquiryresponseactionid=inquiryres1_.inquiryresponseactionid
where inquiryres0_.inquirySessionId=? order by inquiryres0_.createDate
Looking at the first SQL, it's quite evident that the JPQL does not really care about joining other entities in InquirySession as all of the select statements are for InquirySession table. It does a separate SELECT statement to join InquiryResponse and thus, no longer has the expected additional ON clause.

Related

Problems GROUP BY SQL Server HIBERNATE

I can not solve the error
Column 'cohort.id' is invalid in the select list because it is not contained
in either an aggregate function or the GROUP BY clause.
The log in my opinion is correct, if you do not use aggregate functions and grouping, then the query is working, but does not perform grouping.
#Query("select i, sum(r.dose) from Inspection i left join fetch i.cohort c
left join fetch c.parent left join fetch i.user left join i.personal p left
join i.result r where i.id in :inspection GROUP by i")
Tell us what the problem may be. I use SQL Server to be more recent 2008
That's what arrives in SQL Server Profiler
exec sp_executesql N'select inspection0_.id as col_0_0_, sum(result5_.dose)
as col_1_0_, cohort1_.id as id1_4_1_, cohort2_.id as id1_4_2_, personal3_.id
as id1_36_3_, inspection0_.id as id1_28_0_, inspection0_.cohort_id as
cohort_11_28_0_, inspection0_.date as date2_28_0_,
inspection0_.exposure_time as exposure3_28_0_, inspection0_.height as
height4_28_0_, inspection0_.intake as intake5_28_0_,
inspection0_.next_measurement as next_mea6_28_0_, inspection0_.note as
note7_28_0_, inspection0_.personal_id as persona12_28_0_, inspection0_.unit
as unit8_28_0_, inspection0_.updated as updated9_28_0_, inspection0_.user_id
as user_id13_28_0_, inspection0_.weight as weight10_28_0_, cohort1_.code as
code2_4_1_, cohort1_.name as name3_4_1_, cohort1_.parent_id as
parent_i6_4_1_, cohort1_.type as type4_4_1_, cohort1_.updated as
updated5_4_1_, cohort1_.user_id as user_id7_4_1_, cohort2_.code as
code2_4_2_, cohort2_.name as name3_4_2_, cohort2_.parent_id as
parent_i6_4_2_, cohort2_.type as type4_4_2_, cohort2_.updated as
updated5_4_2_, cohort2_.user_id as user_id7_4_2_, personal3_.birth_date as
birth_da2_36_3_, personal3_.first_name as first_na3_36_3_,
personal3_.last_name as last_nam4_36_3_, personal3_.middle_name as
middle_n5_36_3_, personal3_.sex as sex6_36_3_, personal3_.tab_number as
tab_numb7_36_3_, personal3_.transfer_id as transfer8_36_3_
from inspection
inspection0_ left outer join cohort cohort1_ on
inspection0_.cohort_id=cohort1_.id left outer join cohort cohort2_ on
cohort1_.parent_id=cohort2_.id left outer join personal personal3_ on
inspection0_.user_id=personal3_.id left outer join person person4_ on
inspection0_.personal_id=person4_.id left outer join inspection_result
result5_ on inspection0_.id=result5_.inspection_id where inspection0_.id in
(#P0)
group by inspection0_.id order by inspection0_.id asc ',N'#P0 int',1

While running Hibernate Criteria, HQL query is not created in given order

While running Hibernate Criteria, HQL query is not created in given order
and shows Exception
ERROR SqlExceptionHelper:131 - Unknown column 'stsup4_.SUPPLIER_ID' in 'on clause'
The Generated HQL is not created in expected order.
When I run the same generated HQL in mysql with some changes, I get output.
Java Code is given Below
Session session = connector.getSession();
Criteria cr = session.createCriteria(ST_PRODUCTMASTER.class, "ST_PRODUCT");
cr.createCriteria("ST_PRODUCT.ST_PRODUCT_MANUFACTURER_PARENT", "STPRODMAN", JoinType.LEFT_OUTER_JOIN, Restrictions.eq("PROD_MAN_STATUS", "ACTIVE"));
cr.createCriteria("STPRODMAN.ST_MANUFACTURER", "STMAN", JoinType.LEFT_OUTER_JOIN);
cr.createCriteria("ST_PRODUCT.ST_PRODUCT_SUPPLIER_PARENT", "STPRODSUP", JoinType.LEFT_OUTER_JOIN, Restrictions.eq("PROD_SUPPLIER_STATUS", "ACTIVE"));
cr.createCriteria("STPRODSUP.ST_SUPPLIER", "STSUP", JoinType.LEFT_OUTER_JOIN);
cr.createCriteria("ST_PRODUCT.ST_PRODUCT_RATES", "ZSTPR", JoinType.LEFT_OUTER_JOIN, Restrictions.eqProperty("ST_SUPPLIER.SUPPLIER_ID", "STSUP.SUPPLIER_ID"));
cr.createCriteria("ST_PRODUCT.ST_MEDICINE_CATEGORY", "MEDI_CAT", JoinType.LEFT_OUTER_JOIN);
cr.createCriteria("ST_PRODUCT.ST_TAX_MASTER", "TAX", JoinType.INNER_JOIN);
cr.createCriteria("ST_PRODUCT.ST_UNIT", "UNIT", JoinType.INNER_JOIN);
cr.add(Restrictions.eq("ST_PRODUCT.PRODUCT_STATUS", "ACTIVE"));
ProjectionList p1 = Projections.projectionList();
p1.add(Projections.property("ST_PRODUCT.PRODUCT_ID"));
p1.add(Projections.property("ST_PRODUCT.PRODUCT_NAME"));
p1.add(Projections.property("UNIT.UNIT_DISPLAY_UNIT"));
p1.add(Projections.property("TAX.TAX_PURCHASE"));
p1.add(Projections.property("ST_PRODUCT.PRODUCT2_DISCOUNT"));
p1.add(Projections.property("ST_PRODUCT.PRODUCT2_DIS_AMOUNT"));
p1.add(Projections.property("ST_MEDICINE_CATEGORY.CAT_CATEGORY_ID"));
p1.add(Projections.property("MEDI_CAT.CAT_SHORT_NAME"));
p1.add(Projections.property("UNIT.UNIT_ID"));
p1.add(Projections.property("TAX.TAX_ID"));
//MANUFACTURER
p1.add(Projections.property("STMAN.MAN_ID"));
p1.add(Projections.property("STPRODMAN.BASE_LEVEL"));
p1.add(Projections.property("STPRODMAN.FREE_QTY"));
//SUPPLIER
p1.add(Projections.property("STSUP.SUPPLIER_ID"));
p1.add(Projections.property("STPRODSUP.BASE_LEVEL"));
p1.add(Projections.property("STPRODSUP.FREE_QTY"));
cr.setProjection(p1);
List l = cr.list();
System.out.println("Size items::" + l.size());
ERROR SqlExceptionHelper:131 - Unknown column 'stsup4_.SUPPLIER_ID' in 'on clause'
This it the SQL generated by Hibernate
select
this_.PRODUCT_ID as y0_,
this_.PRODUCT_NAME as y1_,
unit8_.UNIT_DISPLAY_UNIT as y2_,
tax7_.TAX_PURCHASE as y3_,
this_.PRODUCT2_DISCOUNT as y4_,
this_.PRODUCT2_DIS_AMOUNT as y5_,
this_.CAT_CATEGORY_ID as y6_,
medi_cat6_.CAT_SHORT_NAME as y7_,
unit8_.UNIT_ID as y8_,
tax7_.TAX_ID as y9_,
stman2_.MAN_ID as y10_,
stprodman1_.BASE_LEVEL as y11_,
stprodman1_.FREE_QTY as y12_,
stsup4_.SUPPLIER_ID as y13_,
stprodsup3_.BASE_LEVEL as y14_,
stprodsup3_.FREE_QTY as y15_
from
ST_PRODUCTMASTER this_
left outer join
ST_MEDICINE_CATEGORY medi_cat6_
on this_.CAT_CATEGORY_ID=medi_cat6_.CAT_CATEGORY_ID
left outer join
ST_PRODUCT_MANUFACTURER stprodman1_
on this_.PRODUCT_ID=stprodman1_.PRODUCT_ID
and (
stprodman1_.PROD_MAN_STATUS=?
)
left outer join
ST_MANUFACTURER stman2_
on stprodman1_.MAN_ID=stman2_.MAN_ID
left outer join
ST_PRODUCT_RATES zstpr5_
on this_.PRODUCT_ID=zstpr5_.PRODUCT_ID
and (
zstpr5_.SUPPLIER_ID=stsup4_.SUPPLIER_ID
)
left outer join
ST_PRODUCT_SUPPLIER stprodsup3_
on this_.PRODUCT_ID=stprodsup3_.PRODUCT_ID
and (
stprodsup3_.PROD_SUPPLIER_STATUS=?
)
left outer join
ST_SUPPLIER stsup4_
on stprodsup3_.SUPPLIER_ID=stsup4_.SUPPLIER_ID
inner join
ST_TAX_MASTER tax7_
on this_.TAX_ID=tax7_.TAX_ID
inner join
ST_UNIT unit8_
on this_.UNIT_ID=unit8_.UNIT_ID
where
(
this_.PRODUCT_DELETED <> 'DELETED'
)
and this_.PRODUCT_STATUS=?
zstpr5_ is generated before stsup4_
and thus zstpr5_.SUPPLIER_ID=stsup4_.SUPPLIER_ID
is not accessible
left outer join
ST_PRODUCT_RATES zstpr5_
on this_.PRODUCT_ID=zstpr5_.PRODUCT_ID
and (
zstpr5_.SUPPLIER_ID=stsup4_.SUPPLIER_ID
)
left outer join
ST_PRODUCT_SUPPLIER stprodsup3_
on this_.PRODUCT_ID=stprodsup3_.PRODUCT_ID
and (
stprodsup3_.PROD_SUPPLIER_STATUS=?
)
left outer join
ST_SUPPLIER stsup4_
on stprodsup3_.SUPPLIER_ID=stsup4_.SUPPLIER_ID
ACTUAL EXPECTED ORDER IS
left outer join
ST_PRODUCT_SUPPLIER stprodsup3_
on this_.PRODUCT_ID=stprodsup3_.PRODUCT_ID
and (
stprodsup3_.PROD_SUPPLIER_STATUS=?
)
left outer join
ST_SUPPLIER stsup4_
on stprodsup3_.SUPPLIER_ID=stsup4_.SUPPLIER_ID
left outer join
ST_PRODUCT_RATES zstpr5_
on this_.PRODUCT_ID=zstpr5_.PRODUCT_ID
and (
zstpr5_.SUPPLIER_ID=stsup4_.SUPPLIER_ID
)
Hibernate is generating a number with table name,
1_, 2_ , 3_
even though while creating SQL this order is not maintained,
it is not even created in the order we give.
Since you haven't posted your mapping file, I'll explain how Hibernate orders the joins.
Hibernate uses the mapping xml file to figure out the order of joins, so if you have a relation in it (one-to-many or any other tag) for that table, just move it above the other table's tag.
You can read more about it here.

String parameter in Hibernate query

I have changed PK in all tables from int ID to UUID (VARCHAR), but after that this query cannot be executed.
String HQLselect = "from Person person " +
"left join fetch person.researchGroups "+
"left join fetch person.personOptParamVals paramVal "+
"left join fetch paramVal.personOptParamDef paramDef "+
"where person.personId = :id";
Person foundUser = (Person) getHibernateTemplate().findByNamedParam(HQLselect, "id", id);
Error is:
Exception in thread "AWT-EventQueue-0" org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; SQL [select person0_.PERSON_ID as PERSON1_32_0_, researchgr1_.RESEARCH_GROUP_ID as RESEARCH1_40_1_, personoptp2_.PERSON_OPT_PARAM_DEF_ID as PERSON1_36_2_, personoptp2_.PERSON_ID as PERSON2_36_2_, personoptp3_.PERSON_OPT_PARAM_DEF_ID as PERSON1_34_3_, person0_.AUTHENTICATION as AUTHENTI2_32_0_, person0_.AUTHORITY as AUTHORITY32_0_, person0_.CONFIRMED as CONFIRMED32_0_, person0_.DATE_OF_BIRTH as DATE5_32_0_, person0_.DEFAULT_GROUP_ID as DEFAULT17_32_0_, person0_.EDUCATION_LEVEL_ID as EDUCATION18_32_0_, person0_.EMAIL as EMAIL32_0_, person0_.FB_UID as FB7_32_0_, person0_.GENDER as GENDER32_0_, person0_.GIVENNAME as GIVENNAME32_0_, person0_.LATERALITY as LATERALITY32_0_, person0_.NOTE as NOTE32_0_, person0_.PASSWORD as PASSWORD32_0_, person0_.PHONE_NUMBER as PHONE13_32_0_, person0_.REGISTRATION_DATE as REGISTR14_32_0_, person0_.SURNAME as SURNAME32_0_, person0_.USERNAME as USERNAME32_0_, researchgr1_.DESCRIPTION as DESCRIPT2_40_1_, researchgr1_.PAID_ACCOUNT as PAID3_40_1_, researchgr1_.OWNER_ID as OWNER5_40_1_, researchgr1_.TITLE as TITLE40_1_, researchgr1_.OWNER_ID as OWNER5_32_0__, researchgr1_.RESEARCH_GROUP_ID as RESEARCH1_0__, personoptp2_.PARAM_VALUE as PARAM3_36_2_, personoptp2_.PERSON_ID as PERSON2_32_1__, personoptp2_.PERSON_OPT_PARAM_DEF_ID as PERSON1_1__, personoptp2_.PERSON_ID as PERSON2_1__, personoptp3_.IS_DEFAULT as IS2_34_3_, personoptp3_.PARAM_DATA_TYPE as PARAM3_34_3_, personoptp3_.PARAM_NAME as PARAM4_34_3_ from PERSON person0_ left outer join RESEARCH_GROUP researchgr1_ on person0_.PERSON_ID=researchgr1_.OWNER_ID left outer join PERSON_OPT_PARAM_VAL personoptp2_ on person0_.PERSON_ID=personoptp2_.PERSON_ID left outer join PERSON_OPT_PARAM_DEF personoptp3_ on personoptp2_.PERSON_OPT_PARAM_DEF_ID=personoptp3_.PERSON_OPT_PARAM_DEF_ID where person0_.PERSON_ID=?]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query
Caused by: ERROR 42818: Comparisons between 'INTEGER' and 'VARCHAR (UCS_BASIC)' are not supported. Types must be comparable. String types must also have matching collation. If collation does not match, a possible solution is to cast operands to force them to the default collation (e.g. SELECT tablename FROM sys.systables WHERE CAST(tablename AS VARCHAR(128)) = 'T1')
I have tried escape ID with ' ', but it didn't change anything. How can I fix it? Thank you.

Hibernate setMaxResults() with H2 SqlGrammarException

I'm attempting to get a certain number of rows from the database given a certain user and a max amount. Here is what the code looks like currently:
#Override
public Collection<TestObject> findMaxByUser(User _user, int _max) {
if (_max <= 0) {
throw new IllegalArgumentException("max <= 0: " + _max);
}
Long rowCount = (Long)createCriteria()
.add(Restrictions.eq("m_queryUser", _user))
.setProjection(Projections.rowCount())
.uniqueResult();
Collection<TestObject> results = createCriteria()
.add(Restrictions.eq("m_queryUser", _user))
.setFirstResult(1)
.setMaxResults(_max)
.list();
final int count = rowCount.intValue();
final int totalCount = count > results.size()
? count : results.size();
return results;
This results in a org.hibernate.SQLGrammarException: could not prepare statement error.
The strange thing is, if I change DB implementations to Derby, the code works fine. But there's something goofy happening using H2 when I try to use .setMaxResults(). If I use .setFetchSize() instead it'll return all the results no problem, but going back to .setMaxResults() produced the above error.
Any help/information would be great.
Caused-by trace:
Caused by: org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "SELECT THIS_.ID AS ID1_0_5_, THIS_.CREATED_ON AS CREATED2_0_5_, THIS_.UPDATED_ON AS UPDATED3_0_5_, THIS_.VERSION AS VERSION4_0_5_, THIS_.FAVORITE_QUERY AS FAVORITE6_0_5_, THIS_.NAME AS NAME5_0_5_, THIS_.USER_KEY AS USER7_0_5_, USERQUERY2_.ID AS ID1_2_0_, USERQUERY2_.CREATED_ON AS CREATED2_2_0_, USERQUERY2_.UPDATED_ON AS UPDATED3_2_0_, USERQUERY2_.VERSION AS VERSION4_2_0_, USERQUERY2_.MAX_RESULTS AS MAX5_2_0_, USERQUERY2_.PROPERTIES AS PROPERTI6_2_0_, USERQUERY2_.QUERY_STRING AS QUERY7_2_0_, USERQUERY2_.USER_KEY AS USER9_2_0_, USERQUERY2_.TARGETS AS TARGETS8_2_0_, EXTUSER3_.EXT_USER AS EXT1_4_1_, EXTUSER3_.CREATED_ON AS CREATED2_4_1_, EXTUSER3_.UPDATED_ON AS UPDATED3_4_1_, EXTUSER3_.VERSION AS VERSION4_4_1_, M_SORTS4_.USER_QUERIES AS USER1_2_7_, QUERYSORT5_.ID AS SORTS2_3_7_, QUERYSORT5_.ID AS ID1_1_2_, QUERYSORT5_.CREATED_ON AS CREATED2_1_2_, QUERYSORT5_.UPDATED_ON AS UPDATED3_1_2_, QUERYSORT5_.VERSION AS VERSION4_1_2_, QUERYSORT5_.ELEMENT_NAME AS ELEMENT5_1_2_, QUERYSORT5_.SORT_ORDER AS SORT6_1_2_, QUERYSORT5_.TYPE AS TYPE7_1_2_, QUERYSORT5_.USER_QUERY AS USER8_1_2_, USERQUERY6_.ID AS ID1_2_3_, USERQUERY6_.CREATED_ON AS CREATED2_2_3_, USERQUERY6_.UPDATED_ON AS UPDATED3_2_3_, USERQUERY6_.VERSION AS VERSION4_2_3_, USERQUERY6_.MAX_RESULTS AS MAX5_2_3_, USERQUERY6_.PROPERTIES AS PROPERTI6_2_3_, USERQUERY6_.QUERY_STRING AS QUERY7_2_3_, USERQUERY6_.USER_KEY AS USER9_2_3_, USERQUERY6_.TARGETS AS TARGETS8_2_3_, EXTUSER7_.EXT_USER AS EXT1_4_4_, EXTUSER7_.CREATED_ON AS CREATED2_4_4_, EXTUSER7_.UPDATED_ON AS UPDATED3_4_4_, EXTUSER7_.VERSION AS VERSION4_4_4_ FROM IES_TEST_SCHEMA.LES_FAVORITES THIS_ LEFT OUTER JOIN IES_TEST_SCHEMA.LES_USER_QUERIES USERQUERY2_ ON THIS_.FAVORITE_QUERY=USERQUERY2_.ID LEFT OUTER JOIN IES_TEST_SCHEMA.LES_USERS EXTUSER3_ ON USERQUERY2_.USER_KEY=EXTUSER3_.EXT_USER LEFT OUTER JOIN IES_TEST_SCHEMA.LES_USER_QUERIES_SORTS M_SORTS4_ ON USERQUERY2_.ID=M_SORTS4_.USER_QUERIES LEFT OUTER JOIN IES_TEST_SCHEMA.LES_QUERY_SORTS QUERYSORT5_ ON M_SORTS4_.SORTS=QUERYSORT5_.ID LEFT OUTER JOIN IES_TEST_SCHEMA.LES_USER_QUERIES USERQUERY6_ ON QUERYSORT5_.USER_QUERY=USERQUERY6_.ID INNER JOIN IES_TEST_SCHEMA.LES_USERS EXTUSER7_ ON THIS_.USER_KEY=EXTUSER7_.EXT_USER WHERE THIS_.USER_KEY=? OFFSET[*] 1 ROWS FETCH NEXT 2 ROWS ONLY "; SQL statement:
select this_.id as id1_0_5_, this_.created_on as created2_0_5_, this_.updated_on as updated3_0_5_, this_.version as version4_0_5_, this_.favorite_query as favorite6_0_5_, this_.name as name5_0_5_, this_.user_key as user7_0_5_, userquery2_.id as id1_2_0_, userquery2_.created_on as created2_2_0_, userquery2_.updated_on as updated3_2_0_, userquery2_.version as version4_2_0_, userquery2_.max_results as max5_2_0_, userquery2_.properties as properti6_2_0_, userquery2_.query_string as query7_2_0_, userquery2_.user_key as user9_2_0_, userquery2_.targets as targets8_2_0_, extuser3_.ext_user as ext1_4_1_, extuser3_.created_on as created2_4_1_, extuser3_.updated_on as updated3_4_1_, extuser3_.version as version4_4_1_, m_sorts4_.user_queries as user1_2_7_, querysort5_.id as sorts2_3_7_, querysort5_.id as id1_1_2_, querysort5_.created_on as created2_1_2_, querysort5_.updated_on as updated3_1_2_, querysort5_.version as version4_1_2_, querysort5_.element_name as element5_1_2_, querysort5_.sort_order as sort6_1_2_, querysort5_.type as type7_1_2_, querysort5_.user_query as user8_1_2_, userquery6_.id as id1_2_3_, userquery6_.created_on as created2_2_3_, userquery6_.updated_on as updated3_2_3_, userquery6_.version as version4_2_3_, userquery6_.max_results as max5_2_3_, userquery6_.properties as properti6_2_3_, userquery6_.query_string as query7_2_3_, userquery6_.user_key as user9_2_3_, userquery6_.targets as targets8_2_3_, extuser7_.ext_user as ext1_4_4_, extuser7_.created_on as created2_4_4_, extuser7_.updated_on as updated3_4_4_, extuser7_.version as version4_4_4_ from IES_TEST_SCHEMA.les_favorites this_ left outer join IES_TEST_SCHEMA.les_user_queries userquery2_ on this_.favorite_query=userquery2_.id left outer join IES_TEST_SCHEMA.les_users extuser3_ on userquery2_.user_key=extuser3_.ext_user left outer join IES_TEST_SCHEMA.les_user_queries_sorts m_sorts4_ on userquery2_.id=m_sorts4_.user_queries left outer join IES_TEST_SCHEMA.les_query_sorts querysort5_ on m_sorts4_.sorts=querysort5_.id left outer join IES_TEST_SCHEMA.les_user_queries userquery6_ on querysort5_.user_query=userquery6_.id inner join IES_TEST_SCHEMA.les_users extuser7_ on this_.user_key=extuser7_.ext_user where this_.user_key=? offset 1 rows fetch next 2 rows only [42000-171]
It sounds like you are not using the right dialect...
Double check what it is set to.
hibernate.dialect=org.hibernate.dialect.H2Dialect

How to join two unrelated entities using JPA and Hibernate

I have two tables - one containing Address and another containing Photographs. The only common field between them is the PersonID. These were mapped to two POJO Classes Address and Photo. I was able to fetch details in these tables by creating criteria and adding restrictions on the fields . How should we write a join on the two tables. Is it possible to get the result as two objects -Address and Photo.
I want to do a left join so that i can get records of persons without photos as well.
I have read that this is possible only using hql but Can this be done using criterias as well?
You can easily write HQL query that will return result as two objects using Theta Join (as Adrian noted). Here is an example:
String queryText = "select address, photo from Address address, Photo photo "
+ " where address.personID=photo.personId";
List<Object[]> rows = session.createQuery(queryText).list();
for (Object[] row: rows) {
System.out.println(" ------- ");
System.out.println("Address object: " + row[0]);
System.out.println("Photo object: " + row[1]);
}
As you can see query returns list of Object[] arrays that represents each fetched row. First element of this array will contain one obejct and second element - another.
EDIT:
In case of left join I think you need to use native SQL query (not HQL query). Here how you can do this:
String queryText = "select address.*, photo.* from ADDRESS address
left join PHOTO photo on (address.person_id=photo.person_id)";
List<Object[]> rows = sess.createSQLQuery(queryText)
.addEntity("address", Address.class)
.addEntity("photo", Photo.class)
.list();
This should work for your case.
Basically, you have two options:
Since Hibernate 5.1, you can use ad-hoc joins for unrelated entities.
Tuple postViewCount = entityManager.createQuery(
"select p as post, count(pv) as page_views " +
"from Post p " +
"left join PageView pv on p.slug = pv.slug " +
"where p.title = :title " +
"group by p", Tuple.class)
.setParameter("title", "High-Performance Java Persistence")
.getSingleResult();
Prior to Hibernate 5.1, you could only use theta-style joins. However, a theta-style join is equivalent to an equijoin, hence you can only emulate INNER JOINs not OUTER JOINs.
List<Tuple> postViewCount = entityManager.createQuery(
"select p as post, count(pv) as page_views " +
"from Post p, PageView pv " +
"where p.title = :title and " +
" ( p.slug = pv.slug ) " +
"group by p", Tuple.class)
.setParameter("title", "Presentations")
.getResultList();
Finally after 12 years the Hibernate team has implemented such a feature
From Hibernate docs:
The FROM clause can also contain explicit relationship joins using the join keyword. These joins can be either inner or left outer style joins.
List<Person> persons = entityManager.createQuery(
"select distinct pr " +
"from Person pr " +
"join pr.phones ph " +
"where ph.type = :phoneType", Person.class )
.setParameter( "phoneType", PhoneType.MOBILE )
.getResultList();
List<Person> persons = entityManager.createQuery(
"select distinct pr " +
"from Person pr " +
"left join pr.phones ph " +
"where ph is null " +
" or ph.type = :phoneType", Person.class )
.setParameter( "phoneType", PhoneType.LAND_LINE )
.getResultList();
Or you can use WITH and ON keywords. A remark on those
The important distinction is that in the generated SQL the conditions
of the WITH/ON clause are made part of the ON clause in the generated
SQL, as opposed to the other queries in this section where the
HQL/JPQL conditions are made part of the WHERE clause in the generated
SQL.
Example
List<Object[]> personsAndPhones = session.createQuery(
"select pr.name, ph.number " +
"from Person pr " +
"left join pr.phones ph with ph.type = :phoneType " )
.setParameter( "phoneType", PhoneType.LAND_LINE )
.list();
I am currently eager to try the new feature.
Joining two unrelated entities are possible in Hibernate 5.1.
Eg :
select objA from ObjectA objA
JOIN ObjectB objB on objB.variable = objA.variable
where objA.id = 1
It's best to have a class containing those classes you want to join to have them all together.
But if you are joining these tables just for some occasional purposes, you can use criteria and manually load data from each table and put them together. (and yes, you can have these tables' data separately if for Address and Photo there are two separate classes and tables)
What you are looking for is
HQL
Join on fields that you haven't modeled as relationships
Left Join
(During the time the question was first asked and this answer was given) Hibernate supports Theta Join which allows you to do 1 & 2. However, only inner join is available for theta join style.
Personally I would recommend you to model proper relationships, so you just need 1 & 3 which is well-supported in HQL.
(Another answer actually provided an update on new Hibernate feature that provides such feature, that you may simply refer to)

Categories