JPA: TypedQuery sometimes returns null instead of NoResultException

hql, jpa, jpa-2.0

Solution

It looks like a correct behaviour for me.

`NoResultException` is thrown when no rows are returned, but `sum` returns exactly one row with `null` value in your case. From JPA 2.0 Specification:

If SUM, AVG, MAX, or MIN is used, and there are no values to which the aggregate function can be applied, the result of the aggregate function is NULL.

If you want to get `0` instead of `null`, use `coalesce`:

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

Problem

Usually I work with NoResultException to return an "empty" object, e.g. an empty error list or new BigInteger("0"), if I get no results from a TypedQuery. Now it turned out that this sometimes doesn't work. Suddenly getSingleResult() returns null instead of causing a NoResultException, and I don't understand why. Look this example: ``` 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"); } } ``` The important part of the Entity... ``` @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"; . . . ``` If I use an accountId which causes no results, I get null instead of NoResultException. Any ideas why this is so? Even Javadoc of TypedQuery says that it has to return 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(); ```

Original source