2012-04-24 102 views
7

通常我使用NoResultException來返回一個「空」對象,例如,一個空的錯誤列表或新的BigInteger(「0」),如果我沒有得到TypedQuery的結果。現在事實證明,這有時不起作用。突然getSingleResult()返回null,而不是導致NoResultException,我不明白爲什麼。看看這個例子:JPA:TypedQuery有時返回null而不是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"); 
    } 
} 

實體的重要組成部分...

@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"; 
. 
. 
. 

如果我使用這將導致沒有結果的帳戶ID,我得到空的,而不是NoResultException。任何想法爲何如此?即使TypedQuery的Javadoc說它必須返回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(); 

回答

19

它對我來說看起來像是正確的行爲。

NoResultException當沒有行返回時拋出,但sum返回恰好一行,null值在你的情況。從JPA 2.0規格:

如果SUM,AVG,MAX,MIN或使用,並且不存在值,以該聚合函數可以是施加 ,聚集函數的結果爲NULL。

如果你想獲得的0代替null,使用​​3210:

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

棘手,但解釋它,謝謝。 – Bevor 2012-04-24 11:58:38

+0

我知道空集的AVG,MAX和MIN是未定義的,但是空集的SUM是0.我想知道他們爲什麼會失敗。 – VinyJones 2014-07-04 13:46:04

+0

對於非空集,SUM,AVG,MAX或MIN也可以爲0。返回null確認空集。 – Ritesh 2014-07-06 03:44:11