How to use CASE WHEN in Hibernate Where clause - java

Plase give example for using CASE WHEN in HQL.
I have used following query in my code.
int receiptNumber = 100;
String hql = "SELECT b FROM OOPExtract as b "
+"WHERE "
+" b.tranStatId =" +receiptNumber+ " AND "
+" b.orderType IN ('EMERGENCY', 'PLENARY', 'PETITION','EXTENSION','MOTION') AND "
+" CASE WHEN b.orderType == 'MOTION' " `enter code here`
+ "THEN "
+" b.status = 'MOTION_SIGNED' "
+" ELSE "
+" b.status LIKE '%%' "
+" END "
+" ORDER BY b.oopExtractId DESC";
But when it run it's generate following exception
org.hibernate.hql.ast.QuerySyntaxException: unexpected token: = .....

I've used the following query in a working project. Could use it as a template :)
"SELECT "
+ "CASE WHEN smth.status != 'BATMAN' THEN ... "
+ "ELSE (SELECT ... FROM ... WHERE ... ORDER BY ... DESC limit 1) "
+ "END, "
+ "next_field, "
+ "CASE WHEN smth.status == 'BATMAN' THEN ... "
+ "ELSE ... "
+ "END, "
+ "final_field_which_doesent_have_a_case_logic"
+ "FROM ... the_rest_of_the_normal_query";

This one works with Hibernate 4/JPA and Spring 4 as well!
select
limite
from
Limite limite
join
fetch limite.limiteEnqs enq
join
fetch enq.limiteValors valor
where
limite.id = :limiteId
and :dataReferencia between valor.dtIniVig and valor.dtFimVig
and enq.vrAtributo1 = case limite.atributoId1
when 8 then :produtoId
else enq.vrAtributo1
end

Please try this. Hope it Work.
"SELECT b FROM OOPExtract as b WHERE "
+" b.tranStatId =" +receiptNumber+ " AND "
+" b.orderType IN ('EMERGENCY', 'PLENARY', 'PETITION','EXTENSION','MOTION') AND "
**+" CASE WHEN b.orderType 'MOTION' " `enter code here`
+ "THEN 'MOTION_SIGNED' "
+" ELSE "**
+" b.status LIKE '%%' "
+" END "
+" ORDER BY b.oopExtractId DESC";

Related

CASE expression in JPQL

In my SpringBoot project I have CrudRepository with next method:
public interface LoanRequestRepository extends CrudRepository<LoanRequest, UUID> {
#Query(
value = "select " +
"lr.id as id," +
"lr.state as state," +
"lr.iban as iban," +
"lr.amount as amount," +
"lr.rate as rate," +
"lr.term as term," +
"lr.best_offer as best_offer," +
"lr.contract_number as contract_number," +
"lr.created as created," +
"lr.company_id as company_id," +
"lr.closed as closed," +
"lr.loan_colvir_id as loan_colvir_id," +
"lr.contract_date as contract_date," +
"lr.first_payment_date as first_payment_date, " +
"lr.gesv as gesv, " +
"c.id as comp_id," +
"c.name as comp_name," +
"c.bin as comp_bin," +
"c.colvir_id as comp_colvir_id," +
"c.kod as comp_kod," +
"c.type as comp_type," +
"c.location_address as comp_location_address," +
"c.registration_address as comp_registration_address," +
"c.legal_address as comp_legal_address," +
"c.actual_address as comp_actual_address," +
"c.department_code as comp_department_code," +
"c.department_name as comp_department_name," +
"c.resident as comp_resident," +
"c.created as comp_created," +
"c.registration_date as comp_registration_date," +
"c.economic_sector as comp_economic_sector," +
"c.short_name as comp_short_name," +
"c.colvir_reference_id as comp_colvir_reference_id," +
"c.card_system_id as comp_card_system_id," +
"c.initial_registration as comp_initial_registration " +
"from loan_request lr " +
"left join company c on c.id = lr.company_id " +
"where 1=1 " +
"and case when :amount is not null " +
" then lr.amount = :amount " +
" else 1=1 end " +
"and case when cast(:dateFrom as date) is not null " +
" then lr.created >= cast(:dateFrom as date)" +
" else 1=1 end " +
"and case when cast(:dateTo as date) is not null " +
" then lr.created <= cast(:dateTo as date) " +
" else 1=1 end " +
"and case when :bin is not null " +
" then c.bin like concat('%', :bin, '%') " +
" else 1=1 end " +
"and case when :companyName is not null " +
" then lower(c.name) like lower(concat('%', :companyName, '%')) " +
" else 1=1 end " +
" group by lr.id, c.id " +
"order by " +
" CASE WHEN :isAscending = true THEN :orderBy END ASC, " +
" CASE WHEN :isAscending = false THEN :orderBy END DESC " +
"limit :size offset :page;")
Iterable<LoanRequestDto> findAllLoanRequestDtoByFilters(#Param("dateFrom") LocalDate dateFrom,
#Param("dateTo") LocalDate dateTo,
#Param("bin") String bin,
#Param("amount") BigDecimal amount,
#Param("companyName") String companyName,
#Param("page") Integer page,
#Param("size") Integer size,
#Param("orderBy") String orderBy,
#Param("isAscending") Boolean isAscending);
}
All query works well, but it ignores "order by" with case expression and list comes in inordered way. I am sending values as "lr.iban", "c.name" to orderBy parameter, and if translate it to sql, it works. But in JPQL it does not work.
So, where am I wrong? How can I solve it?
Also, if change last part with CASE expression to the next:
order by CASE WHEN :isAscending = true THEN c.name END ASC
It also works, well in JPQL. List comes in ordered way.

java.util.UnknownFormatConversionException: Conversion

I wrote a script to orchestrate a query on our hive cluster. And this is the place where the error happened:
Result<Record> result = client.doWithRetry(new SQLClient.JooqSQLFunction<Result<Record>>() {
#Override
public Result<Record> apply(Connection conn, DSLContext jooq) throws SQLException, DataAccessException {
return jooq.fetch(String.format(
"select s.name as season_name, r.name as round_name, " +
" g.uuid, g.name, g.create_time, "+
" (select count(*) from picks_questions q where q.round_uuid=r.uuid) as questions_in_round, "+
" (select group_concat(du.yinz_id) from drops_entries e inner join drops_users du on du.uuid=e.user_uuid where g.uuid=e.drop_uuid and e.create_time<r.end_time) as member_yinz_ids, "+
" (select count(*) from drops_entries e inner join drops_users du on du.uuid=e.user_uuid where g.uuid=e.drop_uuid and e.create_time<r.end_time) as member_count, "+
" (select count(*) from drops_messages m where m.drop_uuid=g.uuid and m.send_time>=r.start_time and m.send_time<r.end_time) as messages_sent "+
" from picks_seasons s "+
" inner join picks_rounds r on r.season_uuid=s.uuid "+
" inner join drops g on g.create_time<r.end_time "+
" where g.name not like 'ADMIN_DROP:%' and g.name<>'' "+
" and s.uuid in "+
" ( "+
" select uuid from picks_seasons "+
" where "+
" unix_timestamp('%s') >= unix_timestamp(start_time) " +
" AND " +
" unix_timestamp('%s') < unix_timestamp(end_time) " +
" );",
sqlDTF.print(seg.getStartingInstant()),
sqlDTF.print(seg.getEndingInstant())
));
}
}
I didn't use "'''" at all. Any ideas what went wrong?
Error Traceback:
java.lang.RuntimeException: java.lang.RuntimeException: java.util.UnknownFormatConversionException: Conversion = '''
at workflows.AbstractCopperWorkflow.main(AbstractCopperWorkflow.java:394) ~[na:na]
% Mark is a reserved character in format string of Java. To escape this, we should use %% instead of %.

QuerySyntaxException: expecting OPEN, found 'DESC' near line 1

I want to implement this JPQL query using JPA:
String hql = "SELECT new org.plugin.service.PaymentTransactionsDeclineReasonsDTO(count(e.id) as count, e.status, e.error_class, e.error_message) " +
" FROM " + PaymentTransactions.class.getName() + " e " +
" WHERE e.terminal_id = :terminal_id AND (e.createdAt > :created_at) " +
" AND (e.status != 'approved') " +
" GROUP BY e.error_message " +
" ORDER BY count DESC";
But I get error: Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: expecting OPEN, found 'DESC' near line 1, column 334 [SELECT new org.plugin.service.PaymentTransactionsDeclineReasonsDTO(count(e.id) as count, e.status, e.error_class, e.error_message) FROM org.datalis.plugin.entity.PaymentTransactions e WHERE e.terminal_id = :terminal_id AND (e.createdAt > :created_at) AND (e.status != 'approved') GROUP BY e.error_message ORDER BY count DESC]
What is the proper way to order by count?
You cannot use the SQL keyword COUNT as an alias (not even in lower case). There is no way around it, you have to use alias names that are not SQL keywords (like SELECT, FROM, AS and so on).
I think you should use the following query, which will at least get rid of the error you posted:
String hql = "SELECT "
+ "new org.plugin.service.PaymentTransactionsDeclineReasonsDTO("
+ "count(e.id) as amount, " // <--- alias name changed here
+ "e.status, "
+ "e.error_class, "
+ "e.error_message) "
+ "FROM "
+ PaymentTransactions.class.getName() + " e "
+ "WHERE "
+ "e.terminal_id = :terminal_id "
+ "AND (e.createdAt > :created_at) "
+ "AND (e.status != 'approved') "
+ " GROUP BY e.error_message "
+ " ORDER BY amount DESC"; // <-- alias name used here

HSQLDB: Encountered a duplicated sql alias

When I execute this query using a self-join from my java program
Query query = session.createSQLQuery("SELECT DISTINCT * " +
"FROM lerneinheit AS le1 JOIN lerneinheit AS le2 " +
"ON le1.datum = le2.datum AND le1.pid = le2.pid " +
" WHERE " +
" le1.datum BETWEEN '2016-10-20' AND '2016-10-20' AND " +
" le1.pid = 3 AND " +
" (le1.abgesagtrechtzeitig = false OR le1.nichtabgesagt = true OR le1.erschienen=true) AND " +
" (le2.abgesagtrechtzeitig = false OR le2.nichtabgesagt = true OR le2.erschienen=true) AND " +
" le1.lernid!= le2.lernid AND " +
" (le2.beginn+1 BETWEEN le1.beginn AND le1.ende OR le2.ende-1 BETWEEN le1.beginn AND le1.ende) " +
" ORDER BY le1.beginn");
I get the following error:
org.hibernate.loader.custom.NonUniqueDiscoveredSqlAliasException: Encountered a duplicated sql alias [LERNID] during auto-discovery of a native-sql query
Although it works fine if I do this from phpAdmin. Everything I found on that topic wasn't helpful at all. Anyone got any idea how to solve that?
It may occurred when there are two or more column/alias exists with the SAME NAME in your select query.
Like...
Select A.NAME, A.ADDRESS, B.NAME, B.AGE from TABLE_A A join TABLE_B B on A.SOME_ID = B.SOME_ID;
Encountered a duplicated sql alias [NAME] during auto-discovery of a native-sql query will show.
I'm not sure but the HQL equivalent for != is <>, so you should write "le1.lernid <> le2.lernid AND"
And by the way I recommend :
Query query = session.createSQLQuery("SELECT DISTINCT * " +
"FROM lerneinheit AS le1 JOIN lerneinheit AS le2 " +
"ON le1.datum = le2.datum AND le1.pid = le2.pid " +
" WHERE " +
" le1.datum BETWEEN :dateMin AND :dateMax AND " +
" le1.pid = :le1Pid AND " +
" (le1.abgesagtrechtzeitig = false OR le1.nichtabgesagt = true OR le1.erschienen = true) AND " +
" (le2.abgesagtrechtzeitig = false OR le2.nichtabgesagt = true OR le2.erschienen = true) AND " +
" le1.lernid != le2.lernid AND " +
" (le2.beginn + 1 BETWEEN le1.beginn AND le1.ende OR le2.ende - 1 BETWEEN le1.beginn AND le1.ende) " +
" ORDER BY le1.beginn");
query.setParametter("dateMin", "2016-10-20");
query.setParametter("dateMax", "2016-10-20");
query.setParametter("le1Pid", 3);

Can't figure out why this big double inner join isn't working, but when split it does

Here is my queries split up that work perfectly fine...
String sqlstatement = "SELECT WBLinkWebsiteID, WBLinkCategoryParentID, WBLinkTitle, WBLinkURL FROM WEBSITECATEGORY_TABLE WHERE WBLinkCategoryID = ?";
String[] args = { CategorySubID };
Part 2
sqlstatement = "SELECT LOCATIONS_TABLE.LocationWebsiteID, "
+ "LOCATIONS_TABLE.locationCity, "
+ "LOCATIONS_TABLE.locationState, "
+ "LOCATIONS_TABLE.locationCountry, LOCATIONS_TABLE.locationType, "
+ "LOCATIONS_TABLE.locationUrl, "
+ "PREF_TABLE.Pref_SavedTitle "
+ "FROM PREF_TABLE INNER JOIN "
+ "LOCATIONS_TABLE ON PREF_TABLE.Pref_LocationID = LOCATIONS_TABLE.LocationID "
+ "WHERE "
+ "PREF_TABLE.Pref_SavedTitle = '" + theSavedPref + "' ORDER BY LOCATIONS_TABLE.locationState, LOCATIONS_TABLE.locationCity";
Now here is my attempt to combine the two instead of just having 2 go in row back to back and burn time/resources...
String NewSqlstatement = "SELECT LOCATIONS_TABLE.LocationWebsiteID, "
+ "LOCATIONS_TABLE.locationCity, "
+ "LOCATIONS_TABLE.locationState, "
+ "LOCATIONS_TABLE.locationCountry, "
+ "LOCATIONS_TABLE.locationUrl, "
+ "LOCATIONS_TABLE.LocationID, "
+ "PREF_TABLE.Pref_SavedTitle, "
+ "WEBSITECATEGORY_TABLE.WBLinkTitle, "
+ "WEBSITECATEGORY_TABLE.WBLinkURL "
+ "FROM PREF_TABLE INNER JOIN "
+ "LOCATIONS_TABLE ON PREF_TABLE.Pref_LocationID = LOCATIONS_TABLE.LocationID "
+ "INNER JOIN WEBSITECATEGORY_TABLE "
+ "ON WEBSITECATEGORY_TABLE.WBLinkWebsiteID = PREF_TABLE.Pref_WebsiteID "
+ "WHERE "
+ "PREF_TABLE.Pref_SavedTitle = '" + theSavedPref + "'";
Now when I try to do my "SINGLE" way it keeps returning the WHOLE database of Locations in the LOCATIONS_TABLE query. It doesn't do just the exact ones I need.
I know the query works, because I have tested it here: http://sqlfiddle.com/#!6/ede97/2
Now I know my example on sqlfiddle is using MS Server 2014, but I assumed the syntax should be pretty much the same since its just standard SELECT with inner joins, but I could be wrong?
Anyone know what I'm doing wrong? Any help is greatly appreciated
EDIT - Fixed the SQLFIDDLE, I put the wrong statement in the example
Aren't you missing your filter on WBLinkCategoryID in the combined query. Shouldn't you have this:
...
+ "INNER JOIN WEBSITECATEGORY_TABLE "
+ "ON WEBSITECATEGORY_TABLE.WBLinkWebsiteID = PREF_TABLE.Pref_WebsiteID "
+ "WHERE "
+ "WEBSITECATEGORY_TABLE.WBLinkCategoryID IN (<value1>,...,<valueN>) AND "
+ "PREF_TABLE.Pref_SavedTitle = '" + theSavedPref + "'";

Categories

Resources