web-dev-qa-db-ja.com

Mapを使用してDAOでクエリパラメーターを渡す

次のようなジェネリックのDAO実装を見るのは非常に一般的です。

public List<E> getResultList(String namedQuery, Map<String, Object> parameters) {
    Query query = entityManager.createNamedQuery(namedQuery);
    parameters.entrySet().forEach(e -> query.setParameter(e.getKey(), e.getValue()));
    return query.getResultList();
}

このアプローチにはいくつか問題があります:

  1. 複雑な構造を使用して、キーと値のデータのリストを渡すだけです。
  2. マップの作成は非常に冗長です。

例:

public List<TransacaoTEF> getActiveTransactions1(TipoMensagem tipoMensagem, LocalDate date) {
    Map<String, Object> parameters = new HashMap<>();
    parameters.put("type", tipoMensagem);
    parameters.put("date", date);
    return getResultList("namedQueryXTPO", parameters);
}

これを回避するために、単純なParameterクラスを作成することを考えました。

public List<E> getResultList(String namedQuery, Parameter... parameters) {
    Query query = entityManager.createNamedQuery(namedQuery);
    Arrays.stream(parameters).forEach(p -> query.setParameter(p.getName(), p.getValue()));
    return query.getResultList();
}

public List<E> getResultList(String namedQuery, List<Parameter> parameters) {
    Query query = entityManager.createNamedQuery(namedQuery);
    parameters.forEach(p -> query.setParameter(p.getName(), p.getValue()));
    return query.getResultList();
}   

使用:

public List<TransacaoTEF> getActiveTransactions2(TipoMensagem tipoMensagem, LocalDate date) {
    return getResultList("namedQueryXTPO", 
            new Parameter("type", tipoMensagem), new Parameter("date", date));
}

public List<TransacaoTEF> getActiveTransactions3(TipoMensagem tipoMensagem, LocalDate date) {
    List<Parameter> parameters = Arrays.asList(
            new Parameter("type", tipoMensagem), 
            new Parameter("date", date));
    return getResultList("namedQueryXTPO", parameters);
}   

それはエンジニアリングを超えているか、単なるパラノイアです; p?

3
Rodrigo Menezes

それはエンジニアリングを超えているか、単なるパラノイアです; p?

私もそうだとは思いません。はい、マップは一般的なデータ構造ですが、キーと値またはパラメーターと値のペアが必要なときに最初に利用するものでもあります。したがって、ほとんどの人はそのようにして、残りのコードは責任があるだけで、次のようなことはしません。

Map<String, Object> parameters = new HashMap<>();
parameters.put(null, someValue);
parameters.put("%$@*^%", someOtherValue);

Parameterクラスを使用する場合、マップが提供するもの以外の何かを行うことができます。上記のようにnullパラメータ名を指定しない、またはnull値を送信せずに JDBC NULL などを送信するなど、内部に配置するもののいくつかをアサートまたは検証できます...

地図は単なるバケツです。あなたが入れるのはあなたが得るものです。派手なものは何もありません。アプリケーションが単純で、統制のとれた開発者が少ない場合などは、マップで十分です。

ライブラリを構築している場合、またはいくつかの安全策が講じられていることを確認したい場合は、Parameterクラスの方が適しています。

1
Bogdan

面倒な地図の作成を簡単にするために、私はしばしば小さなユーティリティを作成します。 (スケルトンコード)

Map addKeyValuePairs(Map m, Object...pairs) {
   // TODO test that pairs has an even number
  for (int i=0; i<pairs.length; i+=2) {
     // TODO Add null checks as desired
     m.put(pairs[i].toString(), pairs[I+1].toString());
  }
  return m;
}
1
user949300