2012-04-24 23 views
7

Zazwyczaj pracuję z NoResultException, aby zwrócić "pusty" obiekt, np. pustą listę błędów lub nowy BigInteger ("0"), jeśli nie otrzymam wyników z Wpisywanego Typu. Teraz okazało się, że to czasami nie działa. Nagle getSingleResult() zwraca null zamiast powodować wyjątek NoResultException i nie rozumiem dlaczego. Spójrz na ten przykład:JPA: TypedQuery czasami zwraca wartość null zamiast NoResultException

public BigInteger pointsSumByAccountId(long accountId) 
{ 
    try 
    { 
     TypedQuery<BigInteger> pointsQuery = entityManager.createNamedQuery(Points.SumByAccountId, BigInteger.class); 
     pointsQuery.setParameter(Points.AccountIdParameter, accountId); 

     return pointsQuery.getSingleResult(); 
    } 
    catch (NoResultException e) 
    { 
     return new BigInteger("0"); 
    } 
} 

Ważną częścią Jednostki ...

@NamedQueries({@NamedQuery(name = "Points.sumByAccountId", query = "select sum(p.value) from Points p where p.validFrom <= current_timestamp() and p.validThru >= current_timestamp() and p.account.id = :accountId")}) 
public class Points 
{ 
    private static final long serialVersionUID = -15545239875670390L; 

    public static final String SumByAccountId = Points.class.getSimpleName() + ".sumByAccountId"; 
    public static final String AccountIdParameter = "accountId"; 
. 
. 
. 

Jeśli używam accountid co powoduje żadnych wyników, mam zerowy zamiast NoResultException. Jakieś pomysły, dlaczego tak się dzieje? Nawet Javadoc z TypedQuery mówi, że musi wrócić NoResultException:

/** 
* Execute a SELECT query that returns a single result. 
* 
* @return the result 
* 
* @throws NoResultException if there is no result 
* @throws NonUniqueResultException if more than one result 
* @throws IllegalStateException if called for a Java 
* Persistence query language UPDATE or DELETE statement 
* @throws QueryTimeoutException if the query execution exceeds 
* the query timeout value set and only the statement is 
* rolled back 
* @throws TransactionRequiredException if a lock mode has 
* been set and there is no transaction 
* @throws PessimisticLockException if pessimistic locking 
* fails and the transaction is rolled back 
* @throws LockTimeoutException if pessimistic locking 
* fails and only the statement is rolled back 
* @throws PersistenceException if the query execution exceeds 
* the query timeout value set and the transaction 
* is rolled back 
*/ 
X getSingleResult(); 

Odpowiedz

19

Wygląda prawidłowego zachowania się na mnie.

NoResultException jest generowany, gdy są zwracane żadne wiersze, ale sum powraca dokładnie jeden wiersz z null wartość w Twoim przypadku. Z JPA 2.0 Specyfikacja:

Jeśli SUM, AVG, MAX lub MIN służy, i nie ma żadnych wartości, do których funkcja zbiorcza może zostać stosowane, wynik funkcji zagregowanego jest NULL.

Jeśli chcesz uzyskać 0 zamiast null użyć coalesce:

select coalesce(sum(p.value), 0) ... 
+1

Tricky, ale to wszystko wyjaśnia, dzięki. – Bevor

+0

Rozumiem, że AVG, MAX i MIN dla pustego zestawu są niezdefiniowane, ale SUM z pustego zestawu wynosi 0. Zastanawiam się, dlaczego mu się to nie udaje. – VinyJones

+0

SUMA, AVG, MAX lub MIN może mieć wartość 0 także dla niepustego zestawu. Zwrócenie wartości null potwierdza pusty zbiór. – Ritesh

Powiązane problemy