8

通常、NoResultException を使用して、TypedQuery から結果が得られない場合、空のエラー リストや new BigInteger("0") などの「空の」オブジェクトを返します。これが時々うまくいかないことが判明しました。突然 getSingleResult() が NoResultException を引き起こす代わりに null を返すようになりましたが、その理由がわかりません。この例を見てください:

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

結果のない accountId を使用すると、NoResultException ではなく null が返されます。これがなぜそうなのか、何か考えはありますか?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();
4

1 に答える 1

24

それは私にとって正しい行動のように見えます。

NoResultException行が返されない場合にスローされますが、あなたのケースでは値をsum持つ行を1つだけ返します。nullJPA 2.0 仕様から:

SUM、AVG、MAX、または MIN が使用され、集計関数を適用できる値がない場合、集計関数の結果は NULL になります。

0の代わりに取得したい場合は、次nullを使用しますcoalesce

select coalesce(sum(p.value), 0) ...
于 2012-04-24T11:26:53.747 に答える