java JPA/Hibernate 返回 BigDecimal 不长

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15345440/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 19:18:19  来源:igfitidea点击:

JPA/Hibernate returning BigDecimal not Long

javahibernatejpa

提问by jeff

I'm computing a SUM grouped by months

我正在计算按月分组的 SUM

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

在 Eclipse 调试模式下关闭显示为 BigDecimal。为什么我贴标时会这样

List<Long> resultList = (List<Long>) q.getResultList();

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

编辑 2

I think I am stuck with a BigDecimal? http://weblogs.java.net/blog/mb124283/archive/2007/04/java_persistenc.html

我想我被 BigDecimal 困住了? http://weblogs.java.net/blog/mb124283/archive/2007/04/java_persistenc.html

回答by Jon Skeet

You should already be getting a warning showing that your cast isn't really checking things fully. Type erasuremeans 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 implicitcast to Longwhich fails.

您应该已经收到警告,表明您的演员并没有真正全面检查事情。类型擦除意味着在执行时, aList<Long>和 a之间没有区别List<BigDecimal>。所以演员表成功了,只有后来的隐式演员表Long失败了。

Basically you need to change your query to make sure it creates Longvalues instead.

基本上,您需要更改查询以确保它创建Long值。

回答by LaurentM

I just faced the same problem.

我刚刚面临同样的问题。

One solution is to add scalar (https://stackoverflow.com/a/29479658).

一种解决方案是添加标量 ( 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)

但在我的情况下(带有@Query 注释的 Spring 数据 jpa),我无法添加它。一种解决方法是将结果列表作为List <? extends Number>(Long 和 BigInteger 的超类)获取

Then you can call the Number's method longValue().

然后你可以调用 Number 的方法longValue()

In java 8, your sample could become:

在 Java 8 中,您的示例可能会变成:

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.

此解决方案避免了字符串转换,如果有一天休眠返回 Long,该解决方案将起作用。

回答by Sabyasachi Mukherjee

You should iterate over the results and convert the objects from String:

您应该遍历结果并从 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();
    }