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();
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;
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With