JPA, Oracle, connect by prior, level - invalid identifier - java

I have query like this one:
final String q =
"SELECT level AS \"sibling_level\", tree.* FROM category_view tree " +
"where tree.child_market = :market " +
"connect by prior tree.cate_xre_id = tree.cate_id " +
"start with tree.cate_id = -1 or tree.cate_id = -18";
final Query query = cqb.createNativeQuery(q, params,
NSISegmentationTreeViewImpl.class);
List<NSISegmentationTreeViewImpl> segList = query.getResultList();
category_view is an database view.
I got sometimes:
SQLGrammarException: ORA-00904: "NSISEGMENT0_"."SIBLING_LEVEL": invalid identifier
its not deterministic sometimes i have good result sometimes i have error.
Database ver is 11
Any ideas?
Thanks.
View def:
CREATE OR REPLACE FORCE "CATEGORY_VIEW" ("PARENT_ID", "PARENT_NAME", "CHILD_ID", "CHILD_NAME", "CHILD_TYPE", "CHILD_PRIORITY", "CHILD_MARKET", "CATE_XRE_ID", "CATE_ID") AS
WITH sibling AS
(SELECT
pare.category_id parent_id,
pare.name parent_name,
chld.category_id child_id,
chld.name child_name,
csga.value child_type,
cpra.value child_priority,
cmra.value child_market ,
paxr.sub_category_id cate_xre_id,
pare.category_id cate_id,
)
SELECT
parent_id,
parent_name ,
child_id,
child_name,
child_type,
child_priority,
child_market,
cate_xre_id,
cate_id,
FROM sibling
ORDER BY sibling.child_name;
I removed unnecessary fields, structure is the same.

Related

Hibernate NamedQuery UPDATE statement throws QuerySyntaxException

I encountered a very interesting issue. I want to create an UPDATE statement NamedQuery for my class (I know this is a bit hacky).
The weird thing is if I use positioned parameters in the query like ?1, ?2 etc. it works perfectly. However, if I want to use named parameters like :id, it fails with the following error:
failed because of: org.hibernate.hql.internal.ast.QuerySyntaxException: expecting EOF, found 'consumingTxId' near line 1.
I'm using Kotlin btw.
My entity:
class StateDetailEntity(
#Id
#Column(name = "issue_tx_id")
val issueTxId: String,
#Column(name = "consuming_tx_id")
val consumingTxId: String?
)
My named query:
NamedQuery(
name = "StateDetailEntity.consume",
query = "UPDATE StateDetailEntity SET " +
"consumingTxId = :consumingTxId " +
"WHERE issueTxId = :issueTxId " +
"AND consumingTxId IS NULL"
)
If I add an alias to the table and re-write the name query to like UPDATE StateDetailEntity s SET... I get the following error:
org.hibernate.hql.internal.ast.QuerySyntaxException: expecting EOF, found 's'.
The funny thing is if I change the query like this:
NamedQuery(
name = "StateDetailEntity.consume",
query = "UPDATE StateDetailEntity SET " +
"consumingTxId = ?1 " +
"WHERE issueTxId = ?2 " +
"AND consumingTxId IS NULL"
)
There are no issues at all. Any ideas? Using Hibernate 5.4.32.Final.

sql to hql throwing exception

I'm using hibernate in my project and I'm trying to convert an existing sql query from DaoImplementation class to hql,
The sql query I have is
JdbcTemplate select = new JdbcTemplate(dataSource);
String sql = "SELECT * FROM (SELECT site_id,rtc,sigplan,cycle_time,health,phase_no,phase_time,active_groups,groupscolour,ip "+
"FROM status_data where rtc>='" + fromDate + "' and rtc<'" + toDate + "' and "+
"site_id=" + SiteId + " order by rtc desc limit "+recordLimit+" )as temp ORDER BY RTC ASC";
I wrote the hql version to get data from HealthLog table as
String hql = " select f from (select h from HealthLog h where rtc>='"+fromDate+"' and rtc <'"+toDate+"' "
+ "and siteId = "+siteId+" order by rtc desc limit "+limit+" ) as f order by rtc asc ";
return super.readListByHql(hql);
But the above hql throws the following exception
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 16 [ select f from (select h from com.traff.hibernate.model.HealthLog as h where rtc>='1974-08-01 14:10:00.0' and rtc <'1974-09-01 23:46:20.6' and siteId = 20 order by rtc desc limit 50000 ) as f order by rtc asc ]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:54)
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:47)
at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:79)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:276)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:180)
at org.hibernate.hql.intern
I also tried the below code snippet but that giving me wrong results
Criteria criteria = createEntityCriteria();
criteria.add(Restrictions.ge("rtc", fromDate));
criteria.add(Restrictions.lt("rtc", toDate));
criteria.add(Restrictions.eq("siteId", siteId));
criteria.setMaxResults(limit);
criteria.addOrder(Order.asc("rtc"));
criteria2 = criteria;
criteria2.addOrder(Order.desc("rtc"));
return criteria2.list();
Which is the correct way to achieve the result?
First of all, as already mentioned in the comments, you cannot do a subquery within the FROM clause in HQL.
See: Hibernate Documentation
Secondly, the limit keyword is not supported by HQL.
Usually you would use query.setFirstResult(0) and query.setMaxResults(recordLimit) methods where query has the type of the Query Interface. But since you are using the limit in a subquery, there is no way.
See: How to set a limit to inner query in Hibernate?
Some options:
Use a native SQLQuery
Since you are only sorting in the outer Query. You could only execute the inner query and sort in Java.
Example for Option 2:
Session session = factory.openSession();
Query query = session
.createQuery("FROM HealthLog "
+ "WHERE rtc >= :rtcL and rtc < :rtcG and siteId = :siteId "
+ "ORDER BY rtc DESC");
query.setParameter("rtcL", fromDate);
query.setParameter("rtcG", toDate);
query.setParameter("siteId", siteId);
query.setFirstResult(0);
query.setMaxResults(recordLimit);
List<HealthLog> res = query.list();
session.close();
Collections.sort(res, new Comparator<HealthLog>() {
public int compare(HealthLog o1, HealthLog o2) {
return o1.getRtc().compareTo(o2.getRtc());
}
});
The query above returns HealthLogs with all attributes. If you want to only retrieve specific attributes, you can add a SELECT new HealthLog(siteId,rtc,sigplan,cycle_time,...) to your Query with a fitting constructor in HealthLog.
Please note that the code snippet might not be ready to use, since i do not know your model and attribute names.

JPA Hibernate JOIN ... ON ... AND

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

How can I get the alias name for my ResultSet from a Subquery?

I have a problem with getting the alias of the columnnames for my ResultSet.
I made a subquery, where i use the alias function(MAX(...) in SQL) but everytime I execute the Statement, I get java.sql.SQLException because the column name is not valid. And I use the current alias where I call the getString - Function of my ResultSet.
This is my SQL-Statement in Eclipse:
String sql = "SELECT a.steelgrade, a.prod_order_id, a.prod_order_item_pos, "
+"a.prod_order_version, a.strip_thickn_aim, a.strip_width_aim, "
+"a.customer, a.order_weight_plan, b.grund_kommlos, b.coil_weight "
+"FROM (SELECT prod_order_id, prod_order_item_pos, "
+ "MAX (prod_order_version) AS max_version "
+ "FROM production_order "
And in the ResultSet while.next()-Loop:
prod_order_version = AuftraegeProduction.getString("max_version");
This is the whole SQL-Statement( in the Database it works fine!):
SELECT a.steelgrade, a.prod_order_id, a.prod_order_item_pos,
a.prod_order_version, a.strip_thickn_aim, a.strip_width_aim,
a.customer, a.order_weight_plan, b.grund_kommlos, b.coil_weight
FROM (SELECT prod_order_id, prod_order_item_pos,
MAX (prod_order_version) AS max_version
FROM production_order
GROUP BY prod_order_id, prod_order_item_pos) c
JOIN
production_order a
ON a.prod_order_id = c.prod_order_id
AND a.prod_order_item_pos = c.prod_order_item_pos
AND a.prod_order_version = c.max_version
JOIN pps_plan_slab b
ON b.prod_order_id = c.prod_order_id
AND b.prod_order_item_pos = c.prod_order_item_pos
AND b.prod_order_version = c.max_version
WHERE a.strip_thickn_aim > 1.78
AND a.strip_thickn_aim < 3.26
AND a.steelgrade = 'M4R51'
AND a.prod_order_id NOT BETWEEN '0999551' AND '0999599'
AND a.strip_width_aim BETWEEN 1126 AND 1166
AND NVL (a.order_weight_plan, 0) > 0
AND a.order_weight_plan >= b.coil_weight
ORDER BY prod_order_id ASC
Anyone have a suggestion?
Maurice
when using aggregate functions max(),min(),sum(),... you must use group by clause clause.

How can I execute an update (named query) in Hibernate Template?

I have a namedQuery like this:
#NamedQueries ({ ...
#NamedQuery(name = "myUpdate", query = "update User set country = 'EN' where user.id = :id")
...
})
In dao layer
getHibernateTemplate().bulkUpdate(...?)
UPDATE
Query query = sessionFactory.getCurrentSession.getNamedQuery("myUpdate");
getHibernateTemplate.bulkUpdate(query.getQueryString(), id);
I get an error:
Hibernate: update User, set country=EN where id = 2343 ORA-00971: missing SET keyword
Anybody now how can resolve this problem?
UPDATE 2
#NamedQuery(name = "myUpdate", query =
"update User set country = 'EN' where
user.profile.id = ?")
OK
#NamedQuery(name = "myUpdate", query =
"update User set country = 'EN' where
user.profile.name = ?")
NOT OK :(
Unfortunately, that feature is missing in spring, as the named queries are supposed to be used only to retrieve data. One thing you can do is (this is a bit of a work around)
Session session = getHibernateTemplate().getSession();
Query query = session.getNamedQuery("myUpdate");
String update = query.getQueryString();
getHibernateTemplate().bulkUpdate(update, [params]);
I would put that in some kind of helper, so your DAO logic doesn't have to go around spring too.
edit
there's a dangling comma between User and set "update User , set country=EN where"
Actually this is a very old question but I had the same problem today. I realized that the update does not work since you cannont have a join inside of a simple UPDATE. That is also the reason why the comma is added. Hibernate tries to rewrite the query like this:
UPDATE User u, Profile p SET u.country = 'EN' where p.name = ? AND p.id = u.profile.id
To solve the issue you need to select the ids from the second table yourself.
#NamedQuery(name = "myUpdate", query = ""
+ " UPDATE User u "
+ " SET country = 'EN' "
+ " WHERE u.profile.id IN ( "
+ " SELECT p.id "
+ " FROM Profile p "
+ " WHERE p.name = ? "
+ " )"

Categories

Resources