2012-04-24 71 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