我正在计算按月分组的SUM
Query q = entityManager.createNativeQuery(qlString);
q.setParameter("program", program);
@SuppressWarnings("unchecked")
List<Long> resultList = (List<Long>) q.getResultList();
long tend = System.currentTimeMillis();
当我传入两个结果列表(已关闭:已关闭项目的结果列表,closedLate:项目结果列表已关闭)进入计算百分比的方法时,我得
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;
}
在Eclipse调试模式下,关闭显示为BigDecimal。为什么这是我判断的时候
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;
}
我想我遇到了BigDecimal? http://weblogs.java.net/blog/mb124283/archive/2007/04/java_persistenc.html
答案 0 :(得分:4)
你应该已经收到一个警告,表明你的演员表并没有真正完整地检查。 Type erasure表示在执行时,List<Long>
和List<BigDecimal>
之间没有区别。所以演员阵容成功了,只有后来的隐式转换为Long
失败了。
基本上,您需要更改查询以确保其创建Long
值。
答案 1 :(得分:1)
我只是遇到了同样的问题。
一种解决方案是添加标量(https://stackoverflow.com/a/29479658)。
但是在我的情况下(带有@Query注释的Spring数据jpa),我无法添加它。
一种解决方法是将结果列表作为List <? extends Number>
(Long和BigInteger的超类)
然后,您可以调用数字的方法longValue()
。
在Java 8中,您的示例可能变为:
List<? extends Number> resultListAsNumber = q.getResultList();
List<Long> resultList = resultListAsNumber.stream().map(i -> i.longValue()).collect(Collectors.toList());
此解决方案避免了String转换,并且如果有一天休眠状态返回Long,则该方法将起作用。
答案 2 :(得分:0)
您应该迭代结果并从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();
}