2013-03-11 31 views
5

jestem obliczania SUM pogrupowane według miesięcyJPA/Hibernate powrocie BigDecimal Niedługo

Query q = entityManager.createNativeQuery(qlString); 
q.setParameter("program", program); 
@SuppressWarnings("unchecked") 
List<Long> resultList = (List<Long>) q.getResultList(); 
long tend = System.currentTimeMillis(); 

Kiedy mijam w dwóch resultsLists (zamknięte: ResultsList Zamkniętych przedmiotów, closedLate: ResultsList przedmiotów Zamknięto późno) do metoda obliczająca procenty, otrzymuję

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; 

}

W trybie debugowania Eclipse zamknięty pokazuje jak BigDecimal. Dlaczego jest to, kiedy 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

myślę siedzę z BigDecimal? http://weblogs.java.net/blog/mb124283/archive/2007/04/java_persistenc.html

+0

Zobacz również http://stackoverflow.com/questions/3574029/what-does-jpa-entitymanager-getsingleresult-return-for -a-count-query – Vadzim

Odpowiedz

4

Powinieneś już otrzymywać ostrzeżenie, że twoja obsada w rzeczywistości nie sprawdza wszystkiego. Type erasure oznacza, że ​​w czasie wykonywania nie ma różnicy między List<Long> i List<BigDecimal>. Tak więc rzutowanie się powiedzie, i to tylko późniejsze, nieostre rzutowanie na , które zawiedzie.

Zasadniczo należy zmienić zapytanie, aby upewnić się, że zamiast tego tworzy wartości Long.

+0

Rozumiem. Moja lista wyników zapytania to [33,23,25,29,15,30, NULL, NULL, NULL, NULL, NULL, NULL] Zgaduję, że NULL przełącza ją na BigDecimal. – jeff

+0

@jeff: Nie, to będzie zależeć od samego zapytania. Wygląda na to, że sądzi, że pobiera dane z liczb całkowitych. –

+0

Twoje prawo o tym. Po prostu poprawiłem moje zapytanie, aby uzyskać 0 zamiast NULL, a lista nadal jest BigDecimal. Zapytanie polega tylko na liczeniu rekordów, więc tak, po prostu dane liczbowe. Jeśli usunę wszystkie generics z mojego zapytania JPA, a następnie w trybie debugowania inpsect resultsList, to pokazuje BigDecimal dla mojej 12 wartości całkowitej. Nie rozumiem, jak inaczej zmodyfikować zapytanie – jeff

0

Należy iteracyjne nad wynikami i przekształcenia obiektów z 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(); 
    } 
+0

BigDecimal # longValue() – MirandaVeracruzDeLaHoyaCardina