case statement in select in jpql - java

I have tried the following but not working.
String mainQuerySt = "select o.progressStatus, "
+ " CASE WHEN o.assigneeEmployee IS NOT NULL THEN o.assigneeEmployee.fullNameSt ELSE '' END as assignee "
+ " from Tt o"
em.createQuery(mainQuerySt).getResultList();
What is wrong with this? Actually, I want to show assigneeEmployee full name if it is not null and otherwise an empty string.
I am using EclipseLink v2.1 as JPA
Thanks in advnace.
EclipseLink Tutorial

You are using o.assigneeEmployee IS NOT NULL, and I assume o.assigneeEmployee is a relationship. Using dot notation forces an inner join, which then will filter out nulls. Try
String mainQuerySt = "select o.progressStatus, "
+ " CASE WHEN assigneeEmployee IS NOT NULL THEN assigneeEmployee.fullNameSt ELSE '' END as assignee "
+ " from Tt o left outer join o.assigneeEmployee assigneeEmployee"
If it does not return the results expected, then you will need to turn on SQL logging to see the SQL produced, and show the results you do expect.

Related

HQL QuerySyntaxException: unexpected AST node

Searched and found a lot of questions about this but nothing for my particular case. I am getting an error on my HQL query, here is the code:
final Query query = session.createQuery(
" SELECT DISTINCT e " +
" FROM Employee e" +
" INNER JOIN Requisition r on r.supervisor = e.id " +
" WHERE r.status = 'Open' " +
" AND r.isEvergreen = false " +
" AND r.isConfidential = false " +
" AND r.employmentType != 'Intern (Fixed Term)' " +
" AND (" +
" CASE WHEN :searchString IS NOT NULL THEN (CONCAT(e.firstName, ' ', e.lastName) LIKE CONCAT('%', TRIM(:searchString), '%')) END)" +
" ORDER BY e.firstName, e.lastName")
.setParameter("searchString", searchString);
And here's the error log:
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected AST node: CASE near line 1, column 329 [ SELECT DISTINCT e FROM <Insert the rest of the query>
The query works if I remove the CASE WHEN statement in the final AND and the setParameter. So that means something is wrong with the final AND (...) and/or the newly introduced parameter.
I am new to Hibernate and am struggling with this since the error message isn't super helpful. Any ideas?
The case you have does not complete the condition.
You can simplify the case as follows :
(coalesce(:searchString,1,0) =1 OR e.firstName||' '|| e.lastName LIKE '%'||:searchString||'%')
The first coalesce will check if searchstring is null , if it is will return 1 and 0 if it is not.
If it returns 1 , the expression after OR will not get evaluated.
If first expression return 0 , the expression after OR will be evaluated
This will fulfill your usecase to apply searchString filter only when it is not null.

Jpa native query doesnt work with group by case/when statement with binding values

Iam trying to use Jpa repository to get data from my sql server using a native query
This is a simple call from my service
repo.testData("h3","h3");
This is my repository query.
Select statement can read the binding variable :level but group by is unable to read it.
#Query(value="SELECT sum(pos.total_weekly_sales) as curr_yr_sales, sum(pos.total_weekly_qty) as curr_yr_qty, pos.vendor_nbr,pos.gmm_id,\n" +
"case \n" +
"when :level = 'h3' then pos.category_id\n" +
"else 0\n" +
"end category_id\n" +
"from dbo.agg_sams_data pos\n" +
"join dbo.calendar_dim cal on pos.wm_year_wk_nbr = cal.wm_year_wk_nbr\n" +
"WHERE \n" +
"cal.calendar_date BETWEEN '2019-09-11' and '2020-09-09'\n" +
"and pos.vendor_nbr = 68494\n" +
"and pos.gmm_id = 45\n" +
"and (:h3Flag = 'N' or pos.category_id = 52)\n" +
"GROUP by pos.vendor_nbr,pos.gmm_id,\n" +
"case \n" +
"when :level='h3' then pos.category_id\n" +
"else 0\n" +
"end",nativeQuery = true)
List<List<Double>> testData(String level,String h3Flag);
And i get the following error
com.microsoft.sqlserver.jdbc.SQLServerException: Column 'dbo.agg_sams_data.category_id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
If i pass the hardcoded value in the group by clause it works fine(as below)
"GROUP by pos.vendor_nbr,pos.gmm_id,\n" +
"case \n" +
"when 'h3'='h3' then pos.category_id\n"
You should try putting pos.category_id into the group by instead of the whole case when statement. The problem is, that SQL Server can't be sure that the parameter in both cases will have the same value so the expressions could be different.

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).

Hibernate HQL compare timestamp to null

I have the following HQL and I would like to know how it handles comparing date column to null. For example what happens in case the givenTime parameter is null. I checked and got empty results. Is it always the case? is it documented?
select mo from MyClassMO mo
where mo.creationDate is not null and mo.creationDate >= (:givenTime)
and what if the givenTime replaced with inner select query which returns null?
thanks
I know you asked about hql but for handling such a cases I prefer using something called Criteria in hibernate. It can be mixed up easy with SQL.
JPA and Hibernate - Criteria vs. JPQL or HQL
Criteria criteria = session
.createCriteria(MyClassMO.class)
.add(Restrictions.isNotNull("creationDate"));
if (givenTime!=null){
criteria.add(Restrictions.ge("creationDate", givenTime));//ge - greater equals
}
List<MyClassMO> result = criteria.list();
If your parameter is nullable, you must manage it manually.
In base of your applied logic, you can write the query.
I suppose some cases (tell me if your is one of these or another).
Case 1: Not consider givenTime in filter
You can wirte this query:
String hql = "select mo from MyClassMO mo" +
" where mo.creationDate is not null";
if (givenTime != null) {
hql += " and mo.creationDate >= (:givenTime)";
}
Case 2: if givenTime is null, put the current date
String hql = "select mo from MyClassMO mo" +
" where mo.creationDate is not null " +
" and mo.creationDate >= COALESCE(:givenTime, current_date())";
Case 3: if givenTime is in subquery returns null, put the current date
String hql = "select mo from MyClassMO mo" +
" where mo.creationDate is not null " +
" and mo.creationDate >= "
" (SELECT COALESCE(:giventime, current_date()) " +
" FROM yourtable WHERE conditions";

Number of characters in sql query result

I am using Spring 3.1.1 with Hibernate 4 and a MSSQL database. Finally, I have been able to query my database with joins in my table that returns the correct answers. Although, it seems that it does not return the entire strings of my messages, but cuts at 29/30 digits. Here is my query:
SQLQuery sql = this.getCurrentSession().createSQLQuery(
"SELECT event.id as eventid, CAST(event_type.type_name AS varchar) as eventtype, event.check_date, event.event_date, event.status, CAST(event_message.message AS varchar) as eventmessage " +
"FROM event_log event " +
"LEFT JOIN event_type " +
"ON (event.event_type_id = event_type.id) " +
"LEFT JOIN event_message " +
"ON (event.event_message_id = event_message.id) " +
"WHERE event.event_type_id = " + jobId +
"ORDER BY eventid");
The result can be:
4506 Database 2014-01-15 14:14:15.02 2014-01-15 14:14:15.02 false Database-connection cannot be
Where the columns are id, task_name, check_date, event_date, status and the message-string at the end. .
The result goes to a ArrayList<Object[]> where I read row[0] etc. to get the entities in the row. The string message gets cut after 29 digits, which is disturbing. Why does it cut the string and how can I fix this? In my database the string exists in it's full and is entitled 400 characters max.
I know this is probably not the best way to query my database, but it will do for my application since it works.
You are using varchar without a length. Never do this!
Replace:
CAST(event_type.type_name AS varchar)
With something like:
CAST(event_type.type_name AS varchar(255))
In some contexts, the default length is 32. In some it is 1. In general, though, always specify the length.
EDIT:
Actually, you probably don't even need the cast. Why not just have event_type.type_name in the select list?

Categories

Resources