JPA Hibernate JOIN ... ON ... AND - java

I use the following query:
SELECT * FROM phaseinproject as pip JOIN projectinrelease pir
ON pip.projectInRelease_id = pir.id
JOIN releaseperiod as rp ON pir.release_id = rp.id
JOIN releasestructure as rs ON rs.id = rp.releaseStructure_id
JOIN phaseinreleasestructure as pirs ON pirs.releaseStructure_id = rs.id
JOIN releasephase as rlp ON rlp.id = pirs.phase_id
AND rlp.id = pip.phase_id
This query works totally fine. I get three results (the amount I expect).
I convert this query to the following HQL query:
TypedQuery<PhaseInProjectOverview> findPhasesInRelease = em.createQuery("SELECT NEW nl.dashboard.dto.out.PhaseInProjectOverview(phaseInProject.id, phase.name, phaseInProject.startDate, phaseInProject.plannedEndDate, phaseInProject.endDate) FROM PhaseInProject phaseInProject "
+ "JOIN phaseInProject.projectInRelease projectInRelease "
+ "JOIN projectInRelease.release release "
+ "JOIN release.releaseStructure releaseStructure "
+ "JOIN releaseStructure.phaseInReleaseStructures phaseInReleaseStructure "
+ "JOIN phaseInReleaseStructure.phase phase "
+ "WHERE release.id = :releaseId ORDER BY phaseInReleaseStructure.position, phaseInProject.startDate", PhaseInProjectOverview.class);
findPhasesInRelease.setParameter("releaseId", releaseId);
return findPhasesInRelease.getResultList();
No matter what I try: I get 6 results, because HQL does not seem to support the "JOIN ... ON ... AND ..." sql syntax.
Does anyone know how to solve this problem?
edit:
I added my own answer with the used solution. Thank you all for the answers/pointers.

Try the with keyword: phaseInReleaseStructure.phase phase WITH phase.id = phaseInProject.phase_id - this should result in SQL like releasephase as rlp ON rlp.id = pirs.phase_id AND rlp.id = pip.phase_id
Alternatively just add that condition in the where clause:
... WHERE release.id = :releaseId AND phase.id = phaseInProject.phase_id ...

I solved my problem with an extra WHERE clause:
phase.id = phaseInProject.phase.id
Now I get the results I was expecting.
The 'WITH' keyword does not seem to work with multiple entities. When I try, I get an exception:
HQL error: with-clause referenced two different from-clause elements
When trying to use the 'ON' syntax like JOIN phaseInReleaseStructure.phase phase ON phase.id = phaseInProject.id, I get another error:
unexpected token: ON near line 1, column 473

Related

Query String with native query and ordered parameter, sql doesn't work

I have the following code
#Query(nativeQuery = true, value = "select e.* from event e"
+ " join league l on (l.id = e.league_id)"
+ " join sport s on (l.sport_id = s.id)"
+ " join team t1 on (t1.id = e.team_one_id)"
+ " join team t2 on (t2.id = e.team_two_id)"
+ " join country c on (c.id = l.country_id)"
+ " where l.name LIKE %?1%")
Page<Event> getAllEventsFiltered(final PageRequest of, final String filter);
If execute this SQL into database I receive a lot of results but when is executed from java I receive no one result in the same SQL.
I already tried:
where l.name LIKE %?#{escape([1])} escape ?#{escapeCharacter()}
but just works to begins and I needs for both begin and end.
JDBC parameters can only be included in very specific places in a SQL statement. They are not replaced as strings in the SQL statement but they are applied. The specific valid places change from database to database, and also depend on the JDBC driver variant/version.
The general rule is that a parameter can be applied where a single value would be present. String parameters should not be enclosed in single quotes as a VARCHAR would be.
One option to make it compliant, is to place the parameter isolated from other text, for example by using the CONCAT() function. Your query could be rephrased as:
#Query(nativeQuery = true, value = "select e.* from event e"
+ " join league l on (l.id = e.league_id)"
+ " join sport s on (l.sport_id = s.id)"
+ " join team t1 on (t1.id = e.team_one_id)"
+ " join team t2 on (t2.id = e.team_two_id)"
+ " join country c on (c.id = l.country_id)"
+ " where l.name LIKE concat('%', ?1, '%')") // change here
Nevertheless, the specific syntax change can be different depending on the database you are using (that you haven't mentioned).

#SQLResultSetMapping Column not found issue

I have a query like so
FROM RUN cr
LEFT JOIN OFFER_SET os ON cr.ID = os.RUN_ID
LEFT JOIN AA aa ON cr.ID = aa.RUN_ID
LEFT JOIN POLICY ex ON cr.ID = ex.RUN_ID
WHERE cr.ID = '1d4101ea2'
and created a mapping entity so I could get a result set back in the proper format. That looks like this.
#Entity
#SqlResultSetMapping(name="OutcomeDetails",
entities={
#EntityResult(entityClass=OutcomeDetailsEntity.class, fields={
#FieldResult(name="reason", column="REASON_CD"),
#FieldResult(name="status", column="STATUS_CD"),
#FieldResult(name="countered", column="COUNTERED_FLG"),
#FieldResult(name="id", column="ID"),
#FieldResult(name="version", column="VERSION"),
#FieldResult(name="createdD", column="CREATED_D"),
#FieldResult(name="modifiedD", column="MODIFIED_D"),
#FieldResult(name="corrId", column="CORRELATION_ID"),
#FieldResult(name="policyId", column="POLICY_ID"),
#FieldResult(name="modelId", column="MODEL_ID"),
#FieldResult(name="srcId", column="SRC_ID"),
#FieldResult(name="refId", column="REF_ID"),
#FieldResult(name="serviceName", column="SERVICE_NAME"),
#FieldResult(name="policy", column="POLICY"),
#FieldResult(name="policyVersion", column="POLICY_VERSION"),
})
})
When I run this query in a sql console it works fine. When I run it through the code I get this error
Caused by: java.sql.SQLException: Column 'corrId' not found.
The code looks like this
try {
Query q = cdsEntityManager.createNativeQuery("SELECT aa.REASON_CD, os.COUNTERED_FLG, ex.STATUS_CD, cr.* " +
"FROM RUN cr " +
"LEFT JOIN OFFER_SET os ON cr.ID = os.RUN_ID " +
"LEFT JOIN AA aa ON cr.ID = aa.RUN_ID " +
"LEFT JOIN POLICY ex ON cr.ID = ex.RUN_ID " +
"WHERE cr.ID=:id ", OutcomeDetailsEntity.class);
q.setParameter("id",id);
result = q.getResultList();
} catch (Exception exception) {
I have looked around, and although people have had similar problems none of the solutions there have worked. Is there something I am missing here?
To anyone coming across this later, I needed to change the name attribute and column attribute to the same thing, so it looked like this
#Entity
#SqlResultSetMapping(name="OutcomeDetails",
entities={
#EntityResult(entityClass=OutcomeDetailsEntity.class, fields={
#FieldResult(name="REASON_CD", column="REASON_CD"),
#FieldResult(name="STATUS_CD", column="STATUS_CD"),
#FieldResult(name="COUNTERED_FLG", column="COUNTERED_FLG"),
#FieldResult(name="ID", column="ID"),
#FieldResult(name="VERSION", column="VERSION"),
#FieldResult(name="CREATED_D", column="CREATED_D"),
#FieldResult(name="MODIFIED_D", column="MODIFIED_D"),
#FieldResult(name="CORRELATION_ID", column="CORRELATION_ID"),
#FieldResult(name="POLICY_ID", column="POLICY_ID"),
#FieldResult(name="MODEL_ID", column="MODEL_ID"),
#FieldResult(name="SRC_ID", column="SRC_ID"),
#FieldResult(name="REF_ID", column="REF_ID"),
#FieldResult(name="SERVICE_NAME", column="SERVICE_NAME"),
#FieldResult(name="POLICY", column="POLICY"),
#FieldResult(name="POLICY_VERSION", column="POLICY_VERSION"),
})
})

hibernate +Java query syntax issue

I am getting erro while executing the query.and No proper error are there in the logs.It only says. Error in query findAllfundSalesCreditCalc.Can anybody help what wrong in it.
#NamedQuery(name="findAllfundSalesCreditCalc",query="select distinct FCM from SubFund SF" +
"join Class C on C.id = SF.id" +
"join SC_Class SCC where SCC.classId = C.id" +
"left join FundSalesCreditCalcMethod FCM where FCM.SubFundId = SF.id")
You're missing whitespaces:
#NamedQuery(name="findAllfundSalesCreditCalc",query=
"select distinct FCM from SubFund SF" +
" join Class C on C.id = SF.id" +
" join SC_Class SCC where SCC.classId = C.id" +
" left join FundSalesCreditCalcMethod FCM where FCM.SubFundId = SF.id")
// ^
// | here
Just because you put a concatenated string on a new line in Java doesn't mean that the (Java) whitespace is reflected in your SQL query.

Java JPA - Inner Join Query doesn't work

I'm currently having an issue using Java JPA with EclipseLink - this query:
SELECT VAR_INPUT.*
FROM VAR_INPUT
INNER JOIN TYPE_VAR_INPUT
ON VAR_INPUT.ID_TYPE_VAR_INPUT = TYPE_VAR_INPUT.ID_TYPE_VAR_INPUT
WHERE TYPE_VAR_INPUT.IS_MANDATORY_TYPE_VAR_INPUT=true;
is working fine when run directly on my database, but doesn't work when I use it with JPA.
JPA Query:
#NamedQuery(name = "VarInput.findAVarInputllOfMandatoryType",
query = "SELECT v "
+ "FROM VarInput v "
+ "INNER JOIN TypeVarInput t "
+ "ON v.ID_TYPE_VAR_INPUT = t.ID_TYPE_VAR_INPUT "
+ "WHERE t.isMandatoryTypeVarInput=:isMandatoryTypeVarInput"),
When I execute it in my Java application, I get the following error:
"The field [VAR_INPUT.ID_VAR_INPUT] in this expression has an invalid table in this context."
Exception in thread "AWT-EventQueue-0" Local Exception Stack:
Exception [EclipseLink-6069] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.QueryException
Exception Description: The field [VAR_INPUT.ID_VAR_INPUT] in this expression has an invalid table in this context.
Query: ReadAllQuery(name="VarInput.findAVarInputllOfMandatoryType" referenceClass=VarInput jpql="SELECT v FROM VarInput v INNER JOIN TypeVarInput t ON v.ID_TYPE_VAR_INPUT = t.ID_TYPE_VAR_INPUT WHERE t.isMandatoryTypeVarInput=:isMandatoryTypeVarInput")
at org.eclipse.persistence.exceptions.QueryException.invalidTableForFieldInExpression(QueryException.java:749) at org.eclipse.persistence.exceptions.QueryException.invalidTableForFieldInExpression(QueryException.java:749)
at org.eclipse.persistence.internal.expressions.FieldExpression.validateNode(FieldExpression.java:296)
My tables looks like that:
Table VAR_INPUT(ID_VAR_INPUT, NAME_VAR_INPUT, ID_TYPE_VAR_INPUT)
Table TYPE_VAR_INPUT(ID_TYPE_VAR_INPUT, NAME_TYPE_VAR_INPUT, IS_MANDATORY_VAR_INPUT)
"VAR_INPUT ManyToOne TYPE_VAR_INPUT"
Do you have any idea of why this happens?
NB: The Entities were generated by NetBeans
You don't use inner join in JQPL like that, you join on entity fields. I'm guessing now since you didn't provide entity code, but try this
#NamedQuery(name = "VarInput.findAVarInputllOfMandatoryType",
query = "SELECT v "
+ "FROM VarInput v "
+ "join v.type t "
+ "WHERE t.isMandatoryTypeVarInput=:isMandatoryTypeVarInput")
In this case you don't even need to join, you can simplify the query to this (inner join is implicitly used)
#NamedQuery(name = "VarInput.findAVarInputllOfMandatoryType",
query = "SELECT v "
+ "FROM VarInput v "
+ "WHERE v.type.isMandatoryTypeVarInput=:isMandatoryTypeVarInput")

NamedQuery select first in list

I try to make a namedQuery:
#NamedQuery(name = "Interval.findByMemoryType",
query = "select i from Interval i JOIN i.intervalDatas id "
+ "where id.fragments.memoryType = :memoryType")
My problem is, that fragments is a list of fragment. I'm only interested in memory type of first element in the list.
So I should have something like this:
#NamedQuery(name = "Interval.findByMemoryType",
query = "select i from Interval i JOIN i.intervalDatas id "
+ "(select first(id.fragments)) as fid) where fid.memoryType = :memoryType")
But I get always “The query contains a malformed ending” problem.
Could somebody help me??
You can take the first result:
TypedQuery<Interval> q = em.createQuery ("Interval.findByMemoryType", Interval.class);
q.setParameter("memoryType", memoryType);//+other parameters if you have
Interval interval = q.getSingleResult();
The small disadvantage is that it may load all its intervalDatas (depending on the mapping). Also check the documentation for possible exceptions.

Categories

Resources