From List to int. Unable to convert a query result - java

I have this query:
select count(*) from {Order as or join CustomerOrderStatus as os on
{or:CustomerOrderStatus}={os:pk} join OrderEntry as oe on
{or.pk}={oe.order} join PurchaseAmount as pa on
{or.pointOfSale}={pa.purchaseAmountOwner} join PurchaseAmountTimeSlice
as ts on {pa.pk}={ts.purchaseamount}} where {or:company} in
(8796093710341) and {or:pointOfSale} in (8796097413125)
I have this code in Java to retrieve result:
FlexibleSearchQuery query = new FlexibleSearchQuery(queryBuilder.toString());
List<Integer> result = new ArrayList<Integer>();
result = getFlexibleSearchService().<Integer> search(query).getResult();
I want to take the int value of the count from the result list.
If I write result.get(0) I obtain an error IllegalArgumentException:
java.lang.IllegalArgumentException: invalid pks [4] - unknown typecode 0
at de.hybris.platform.core.WrapperFactory.getCachedItems(WrapperFactory.java:304)
at de.hybris.platform.core.LazyLoadItemList.loadPage(LazyLoadItemList.java:230)
at de.hybris.platform.servicelayer.search.impl.LazyLoadModelList.loadPage(LazyLoadModelList.java:60)
at de.hybris.platform.core.LazyLoadItemList.switchPage(LazyLoadItemList.java:219)
at de.hybris.platform.core.LazyLoadItemList.switchBufferedPageNoLock(LazyLoadItemList.java:475)
at de.hybris.platform.core.LazyLoadItemList.switchBufferedPageSynchronized(LazyLoadItemList.java:467)
at de.hybris.platform.core.LazyLoadItemList.switchBufferedPage(LazyLoadItemList.java:462)
at de.hybris.platform.core.LazyLoadItemList.getOrSwitchBufferedPage(LazyLoadItemList.java:453)
at de.hybris.platform.core.LazyLoadItemList.getOrSwitchBufferedPage(LazyLoadItemList.java:433)
at de.hybris.platform.core.LazyLoadItemList.getBuffered(LazyLoadItemList.java:111)
at de.hybris.platform.core.LazyLoadItemList.get(LazyLoadItemList.java:97)
at java.util.AbstractList$Itr.next(AbstractList.java:358)
at de.hybris.platform.core.internal.BaseLazyLoadItemList$1.next(BaseLazyLoadItemList.java:180)
at java.util.AbstractCollection.toArray(AbstractCollection.java:195)
at java.util.Collections$UnmodifiableCollection.toArray(Collections.java:1059)
How I can get the int value?

Replace count(*) with count({or:Pk}) and set result class of flexible search query to Integer like this query.setResultClassList(Collections.singletonList(Integer.class));

I resolved in this way:
private FlexibleSearchService flexibleSearchService;
#Override
public void onValidate(PurchaseAmountTimeSliceModel paramMODEL, InterceptorContext paramInterceptorContext)
throws InterceptorException {
//.....
final StringBuilder queryBuilder = new StringBuilder();
queryBuilder.append("select {ts.pk}");
queryBuilder.append(
" from {Order as or join CustomerOrderStatus as os on {or:CustomerOrderStatus}={os:pk} join OrderEntry as oe on {or.pk}={oe.order} ");
queryBuilder.append(
"join PurchaseAmount as pa on {or.pointOfSale}={pa.purchaseAmountOwner} join PurchaseAmountTimeSlice as ts on {pa.pk}={ts.purchaseamount}} where ");
if (pointOfSale != null && company != null) {
queryBuilder.append("{or:company} in (" + company.getPk() + ") and {or:pointOfSale} in ("
+ pointOfSale.getPk() + ")");
}
FlexibleSearchQuery query = new FlexibleSearchQuery(queryBuilder.toString());
SearchResult<PurchaseAmountTimeSliceModel> result = flexibleSearchService.search(query);
if (result != null) {
if (result.getCount() >= 10) {
LOG.error("There's already 10 purchase amount time slices configured. You reached the limit.");
throw new InterceptorException(
"There's already 10 purchase amount time slices configured. You reached the limit.");
}
}
//.....
The solution is similar ;)

Related

Single Row Sub query return more than one row

I wrote a SQL query which updates the record, in most cases it runs fine, but from yesterday it fails to update the row.I am currently working on Spring MVC based Web application, in which I need to perform the DML operation by calling update()method.
I am using JDBC template and in my update method i wrote this query.
It fetches the 947 records for January month 2018 and I already checked all records are unique.
I am here stuck, i am not able to find the duplication of record.I thought this exception occurred because of multiple record, but I think i am wrong, there is something which i am not able to identify.
Here is the query:
UPDATE SALARY_DETAIL_REPORT_012018 sd
SET sd.EMP_ID =
(SELECT e.emp_id from EMPLOYEE e
WHERE e.VERIFY_STATUS = 1
AND e.RELIEF_TYPE IS NULL
AND e.emp_code = to_char(sd.emp_code)
AND e.EMP_TYPE_ID!=03)
WHERE EXISTS
(SELECT e.emp_id from EMPLOYEE e
WHERE e.VERIFY_STATUS = 1
AND e.emp_code = to_char(sd.emp_code)
AND e.EMP_TYPE_ID!=03 AND e.RELIEF_TYPE IS NULL)
AND sd.EMP_ID IS NULL
AND sd.REFERENCE_ID LIKE '203-%'
and HERE is Java Code in my DAOImpl class
public void update(String tableSuffix, String regionId, String circleId) {
String tabName = "SALARY_DETAIL_REPORT_" + tableSuffix;
String q = "UPDATE " + tabName + " sd"
+ " SET sd.EMP_ID = (SELECT e.emp_id "
+ " from EMPLOYEE e WHERE e.VERIFY_STATUS = 1 AND e.RELIEF_TYPE IS NULL "
+ " AND e.emp_code = to_char(sd.emp_code) AND e.EMP_TYPE_ID!=03) "
+ " WHERE "
+ " EXISTS (SELECT e.emp_id from EMPLOYEE e WHERE e.VERIFY_STATUS = 1 "
+ " AND e.emp_code = to_char(sd.emp_code) AND e.EMP_TYPE_ID!=03 AND e.RELIEF_TYPE IS NULL) "
+ " AND sd.EMP_ID IS NULL";
if (circleId != null && !circleId.trim().equals("")) {
q += " AND sd.REFERENCE_ID LIKE '" + circleId + "-%' ";
} else {
q += " AND sd.REFERENCE_ID LIKE '" + regionId + "-%' ";
}
// System.out.println("q " + q);
MapSqlParameterSource param = new MapSqlParameterSource();
getNamedParameterJdbcTemplate().update(q, param);
}
Please suggest me the best solution
You need to find the rows that prevent your query from running.
Run this query:
SELECT sd.emp_code, COUNT(*) as cnt
FROM EMPLOYEE e
WHERE e.VERIFY_STATUS = 1 AND
e.RELIEF_TYPE IS NULL AND
e.emp_code = to_char(sd.emp_code) AND
e.EMP_TYPE_ID <> 03
GROUP BY sd.emp_code
HAVING COUNT(*) > 1;
This has the candidate problems. What can you do? The simplest thing is one of the problems:
Change the SELECT to SELECT MAX(sd.emp_code)
Change the WHERE with AND rownum = 1

Wrong BigInteger result using hibernate native query

I'm using Hibernate4 + PostgresSql.
I need to get a list of ids from my DB without getting a whole object.
I use a native query (because it's hierarchical) and it looks like:
String s = hierachical_part_skipped +"select id " +
"from search_hierarchy " +
"order by id";
Query q = getEntityManager().createNativeQuery(s);
List<Long> resList = new ArrayList<>();
List<BigInteger> biglist = q.getResultList();
for (Object id : biglist) {
System.out.print(id+",");
resList.add(id.longValue());
}
Well, 1 time out of three my bigList is filled with wrong values!
I have
10,20,30,40,50,60,70,80,90,100 ... 27350
instead of
1, 2... 2735
(a zero is added to each value).
Native query executed manually not through Hibernate returns correct values.
I've tried retrieving result as List of Object, but the result was the same
I have found a sufficient workaround
s.append("select id \\:\\:numeric " + //that's a hack
"from search_department " +
"order by id");
Query q = getEntityManager().createNativeQuery(s);
List<Long> resList = new ArrayList<>();
List<BigDecimal> biglist = q.getResultList();
for (BigDecimal id : biglist) {
System.out.print(id + ",");
resList.add(id.longValue());
}
Still, I'm wondering why BigInteger works incorrectly

getting error that nested exception is org.hibernate.hql.ast.QuerySyntaxException: Path expected for join

I am new to hibernate and I have a query
select * from Losa_App a
inner join
os_historystep os
on
a.app_ref_no = os.ref_id
where
os.step_name = '011' and app_status = 'R' or app_status = 'S' ;
when i run this query on sqldeveloper it runs and give me the results. Now i translated the query into HBL like
StringBuffer query = new StringBuffer();
List<String> lstObj = new ArrayList<String>();
query.append(" from ");
query.append(getClassName());
query.append(" a inner join "
// + WflWorkflowHistoryStep.class.getName()
+ " OS_HISTORYSTEP os with a.appRefNo = os.ref_id "
+ "where os.step_name = '011' and a.appStatus = 'R' or a.appStatus = 'S' ");
List<LosaApp> result = null;
try {
result = getHibernateTemplate().find(query.toString());
if (CollectionUtils.isNotEmpty(result) {
return result;
}
} catch (Exception e) {
String message = e.getMessage();
System.out.println();
}
return null;
But when this query runs i get exception that
nested exception is org.hibernate.hql.ast.QuerySyntaxException: Path expected for
join! [ from com.thetasp.losa.data.LosaApp a inner join OS_HISTORYSTEP os with
a.appRefNo = os.ref_id where os.step_name = '011' and a.appStatus = 'R'
or a.appStatus = 'S' ]
Why i am getting this error ?
Thanks
Your HQL syntax is wrong.
You need to specify the alias by using the keyword as. E.g:- Losa_App as a
If you give inner join, and have your association mappings done, then you needn't provide the on clause.
If you want to give a.app_ref_no = os.ref_id, then you need not specify inner join. Hibernate will take care of that.
For more info, do have a look at this question.

JPA/Hibernate returning BigDecimal not Long

I'm computing a SUM grouped by months
Query q = entityManager.createNativeQuery(qlString);
q.setParameter("program", program);
#SuppressWarnings("unchecked")
List<Long> resultList = (List<Long>) q.getResultList();
long tend = System.currentTimeMillis();
When I pass in two resultsLists (closed:ResultsList of Closed items, closedLate: ResultsList of items Closed late) into a method that computes percentages, I get
javax.servlet.ServletException: java.lang.ClassCastException: java.math.BigDecimal cannot be cast to java.lang.Long
.
private List<Long> computeOTR(List<Long> closed, List<Long> closedLate) {
List<Long> monthlyOTR = new ArrayList<Long>();
long numerator;
Long denominator;
for (int i = 0; i <11; i++) {
numerator = closed.get(i) - closedLate.get(i); <----java.lang.ClassCastException
denominator = closed.get(i);
long percentage = (int)(numerator * 100.0 / denominator + 0.5);
monthlyOTR.add(i, percentage);
}
return monthlyOTR;
}
In Eclipse debug mode closed is showing as BigDecimal. Why is this when I decalre
List<Long> resultList = (List<Long>) q.getResultList();
EDIT-Hibernate Query:
public List<Long> findClosedLateByProgram(String program) {
long tstart = System.currentTimeMillis();
//#formatter:off
String qlString = "with PRJ as ( " +
"select trunc(END_DATE) as END_DATE, " +
"trunc(NEED_DATE) as NEED_DATE " +
"from (SELECT UNIQUE * FROM TEST where PROGRAM_NAME = :program " +
"AND ACTION_BY_ORG = 'AAA') " +
"), " +
"DATES as ( select add_months(trunc(last_day(SYSDATE)), level-7) as thedate " +
"from dual connect by level <= 12 ) " +
"SELECT nvl(sum(case when NEED_DATE < trunc(thedate,'mm') AND END_DATE between trunc(thedate,'mm') and thedate then 1 end), 0 ) as CLOSED_LATE " +
"FROM DATES, PRJ " +
"GROUP BY thedate ORDER BY thedate";
//#formatter:on
Query q = entityManager.createNativeQuery(qlString);
q.setParameter("program", program);
// q.setParameter("today",date, TemporalType.DATE);
#SuppressWarnings("unchecked")
List<Long> resultList = q.getResultList();
long tend = System.currentTimeMillis();
long elapsed = tend-tstart;
System.out.println("Elapsed Time For Closed But Late: " + elapsed);
return resultList;
}
EDIT 2
I think I am stuck with a BigDecimal?
http://weblogs.java.net/blog/mb124283/archive/2007/04/java_persistenc.html
You should already be getting a warning showing that your cast isn't really checking things fully. Type erasure means that at execution time, there's no difference between a List<Long> and a List<BigDecimal>. So the cast succeeds, and it's only the later implicit cast to Long which fails.
Basically you need to change your query to make sure it creates Long values instead.
I just faced the same problem.
One solution is to add scalar (https://stackoverflow.com/a/29479658).
But in my case (Spring data jpa with #Query annotation), I couldn't add it.
One workaround is to get result list as a List <? extends Number> (superclass of Long and BigInteger)
Then you can call the Number's method longValue().
In java 8, your sample could become:
List<? extends Number> resultListAsNumber = q.getResultList();
List<Long> resultList = resultListAsNumber.stream().map(i -> i.longValue()).collect(Collectors.toList());
This solution avoids String convertion and will work if one day hibernate returns Long.
You should iterate over the results and convert the objects from String:
Query query = createSQLQuery(sql);
List<Long> ids = new java.util.ArrayList<Long>();
java.util.Iterator res = query.list().iterator();
try {
while(res.hasNext()){
ids.add(new Long(res.next().toString()));
}
} catch(Exception ex) {
ex.printStackTrace();
}

SUM result value repeats even with case statement

I'm using posgresql as a database and java as programming language with hibernate. My problem is this query:
select cast(sum(CASE WHEN p.nropack > 0 THEN p.nropack ELSE 0 END) as integer),
cast(sum(CASE WHEN p.nropack < 0 THEN p.nropack ELSE 0 END) as integer),
cast(p.fechareg as date)
from pronostico p
inner join aeropuerto a on (a.idaeropuerto=p.idaeropuerto)
inner join ciudad c on (a.idciudad=c.idciudad)
inner join pais ps on (ps.idpais=c.idpais)
inner join continente ct on (ct.idcontinente=ps.idcontinente)
where c.idciudad=105
group by cast (p.fechareg as date);
As a result I get:
sum;sum;fechareg
30;-15;"2012-11-15"
But when I use it in my program:
public ArrayList<RepKardex> listarKardex(int ciud){
ciud=105;
ArrayList<RepKardex> listaKardex = new ArrayList<>();
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
String q = "select cast(sum( case when p.nropack > 0 then p.nropack ELSE 0 end ) as integer), "
+ "cast(sum( case when p.nropack < 0 then p.nropack ELSE 0 end ) as integer), "
+ "cast(p.fechareg as date) "
+ "from Pronostico p "
+ "inner join Aeropuerto a on (p.idaeropuerto = a.idaeropuerto) "
+ "inner join Ciudad c on (a.idciudad = c.idciudad) "
+ "inner join Pais ps on (c.idpais = ps.idpais) "
+ "inner join Continente ct on (ct.idcontinente = ps.idcontinente) "
+ "where c.idciudad = :ciud "
+ "group by cast(p.fechareg as date) ";
Query query = session.createSQLQuery(q);
query.setInteger("ciud", ciud);
List lista = query.list();
Iterator iter = lista.iterator();
while (iter.hasNext()) {
Object[] row = (Object[]) iter.next();
if (row!=null){
System.out.println("entrantes : "+(Integer)row[0]);
System.out.println("salientes : "+(Integer)row[1]);
RepKardex rep = new RepKardex((int)row[0],(int)row[1],(Date)row[2]);
listaKardex.add(rep);
}
}
tx.commit();
session.close();
return listaKardex;
}
It prints
entrantes: 30
salida: 30
Can someone help me figure out why it repeats the positive numbers even when I use the case statement inside the query? Thanks in advance.
You can simplify your query with LEAST and GREATEST:
SELECT sum(GREATEST(p.nropack, 0))::int AS entrantes
,sum(LEAST(p.nropack, 0))::int AS salida
,p.fechareg::date AS fechareg
from pronostico p
JOIN aeropuerto a ON a.idaeropuerto = p.idaeropuerto
JOIN ciudad c ON c.idciudad = a.idciudad
JOIN pais ps ON ps.idpais = c.idpais
JOIN continente ct ON ct.idcontinente = ps.idcontinente
where c.idciudad = 105
GROUP BY p.fechareg::date;
Other than that it looks just fine. I see no way the second column could return a positive number. Something else must go wrong here.
Edit:
Comment by #hvd helped to find that the client code seems to get confused by identical column names (both sum columns defaulted to "sum"). Explicit column aliases seem to fix this.

Categories