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.
Related
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.
I have a JPQL query in a repository that is the equivalent of the MySQL query below:
SELECT DISTINCT ji.* FROM tracker_job_item AS ji
JOIN tracker_work AS w ON ji.id=w.tracker_job_item_id
JOIN tracker_work_quantity AS wq on w.id=wq.tracker_work_id
WHERE w.work_type = 'CUTTING' AND ji.is_finished=0
GROUP BY wq.tracker_work_id
HAVING ji.quantity != SUM(wq.received_quantity)
The MySQL version works just fine, but the JPQL equivalent gives an exception: Unknown column 'jobitem0_.quantity' in 'having clause'
The JPQL query is like below:
#Query("select distinct ji from JobItem ji" +
" join Work w on ji.id=w.jobItem.id" +
" join WorkQuantity wq on w.id=wq.work.id" +
" where w.workType='CUTTING' and ji.isFinished=false and ji.jobItemName like %:search%" +
" group by ji.id" +
" having ji.quantity != sum(wq.receivedQuantity)")
Page<JobItem> findAllActiveCuttingJobs(Pageable pageable, #Param("search") String search);
Please help me with why I'm getting the error even though the field quantity exists in JobItem.
You can't reference a column in the having clause that isn't in the group by clause, definitely in JPA and (normally at least) in SQL. Looks like MySQL is letting you get away with it but JPA isn't.
See here:
http://learningviacode.blogspot.co.uk/2012/12/group-by-and-having-clauses-in-hql.html
I have problem with my #Repository:
#Repository
public interface RekvZmRepository extends CrudRepository<RekvalZamestn, RekvalZamestnPk> {
#Query(value = "SELECT z.* FROM rek_zm d INNER JOIN proj_a a ON d.id = a.prj_idcislo"
+ " INNER JOIN proj_e e ON a.id = e.id"
+ " INNER JOIN rekv_z z ON d.id = z.id"
+ "WHERE d.id = ?1 AND a.id = ?2 AND e.id = ?3", nativeQuery = true)
public List<RekvalZamestn> getRekvOsOnDoh(Long dhzmrk, Long prj, Long prje);
}
When I run it, result is:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not
extract ResultSet; SQL [n/a]; nested exception is
org.hibernate.exception.SQLGrammarException: could not extract ResultSet
When I run SQL it works, so for me it looks like problem is not with SQL but with my #Query.
Your query, in one-line format (condensing multiple spaces to one space for reasons of, erm, space), equates to
SELECT z.* FROM rek_zm d INNER JOIN proj_a a ON d.id = a.prj_idcislo INNER JOIN proj_e e ON a.id = e.id INNER JOIN rekv_z z ON d.id = z.idWHERE d.id = ?1 AND a.id = ?2 AND e.id = ?3
If you concatenate all the strings in one line like this, it becomes obvious that you are missing a space before the WHERE clause.
change SELECT z.* FROM to SELECT z FROM assuming RekvalZamestn class maps to table rekv_z.
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.
I keep getting errors when trying to get this SQL correct for a JPA repository delete. What is the correct syntax?
#Query("delete * from TS t inner join TSC c ON t.tenantId = c.id where t.id= ?1 AND c.endDate < ?2")
void deleteTSWithExpiredDate(Long id, Date date);
Caused by: java.lang.IllegalArgumentException: node to traverse cannot be null!
at org.hibernate.hql.internal.ast.util.NodeTraverser.traverseDepthFirst(NodeTraverser.java:63)
Another
#Query("delete t.* from TS t inner join TSC c ON t.tenantId = c.id where t.id= ?1 AND c.endDate < ?2")
void deleteTSWithExpiredDate(Long id, Date date);
expecting IDENT, found '*' near line 1, column 10 [delete t.*
Another
#Query("delete t from TS t inner join TSC c ON t.tenantId = c.id where t.id= ?1 AND c.endDate < ?2")
void deleteTSWithExpiredDate(Long id, Date date);
unexpected token: from near line 1, column 10 [delete t
The syntax for bulk delete is:
Query q = session.createQuery("delete Entity where id = :idParam");
// set params here
q.executeUpdate();
However from Hibernate documentation, no joins can be specified in a bulk HQL query. Sub-queries can be used in the where-clause, where the sub-queries themselves can contain joins.