0

私はこのコードの塊、かなり標準的なものを持っています。Java オブジェクトでいくつかのフィルターを取り、フィルターに一致するすべてのレコードを返します。

class MarkFilters {
   Integer idFilter;
   Integer userIDFilter;
   Integer claimIDFilter;
}

List<Integer> findMarksMatchingFilters(MarkFilters filters) {
    String sql = "select id from Mark where 1";

    // This has the values to substitute in for the ?'s in the SQL
    List<Object> parameters = new LinkedList<Object>();

    if (filters.idFilter != null) {
        sql += " and id = ?";
        parameters.add(filters.idFilter);
    }

    if (filters.userIDFilter != null) {
        sql += " and userID = ?";
        parameters.add(filters.userIDFilter);
    }

    if (filters.claimIDFilter != null) {
        sql += " and claimID = ?";
        parameters.add(filters.claimIDFilter);
    }

    return executeSQLWithParameters(sql, parameters);
}

同じ種類のことを行う方法を見つけました:

List<Integer> findMarksMatchingFilters(MarkFilters filters) {
    return executeSQLWithParameters(
            "select * from Mark " +
            "where (? = NULL or id = ?) " +
            "and (? = NULL or userID = ?) " +
            "and (? = NULL or claimID = ?) ",
        filters.idFilter, filters.idFilter,
        filters.userIDFilter, filters.userIDFilter,
        filters.claimIDFilter, filters.claimIDFilter);
}

たとえば、新しい MarkFilters(null, null, 3)をフィードすると、SQL ステートメントは次のようになります。

select * from Mark
where (NULL = NULL or id = NULL)
and (NULL = NULL or userID = NULL)
and (3 = NULL or claimID = 3)

理論的には次のように最適化されます。

select * from Mark where claimID = 3;

私の具体的な質問: その最適化は実際に行われますか?

私のより広い質問: これは従うべき良いパターンですか、それとも私には見えない欠点がありますか?

ありがとう!

4

2 に答える 2

1

いいえ。式NULL = NULLは false と評価されます。

あなたがしたい:

        "select * from Mark " +
        "where (? is NULL or id = ?) " +
        "and (? is NULL or userID = ?) " +
        "and (? is NULL or claimID = ?) ",

MySQL はコンパイル時に定数式を評価すると思います。これは、where節が評価前に単純化されることを意味します。ただし、これを保証する特定の参照がドキュメントに見つかりません。

于 2013-04-23T02:38:19.043 に答える