3

It's very common see a generic's DAO implementation like this:

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();
}

I have some problems with this approach:

  1. Using a complex structure to just pass a list of key & value data.
  2. Map creation is very verbose.

Example:

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);
}

To avoid this I thought in create a simple Parameter class:

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();
}   

Using:

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);
}   

It's over engineering or just paranoia ;p ?

1

It's over engineering or just paranoia ;p ?

I don't think it's either. Yes, a map is a generic data structure but it's also the first thing you reach out for when you need key-value or param-value pairs. So most people do it like that and then the rest of the code is just them being responsible and not do things like this:

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

If you use a Parameter class you can do something extra than what a map gives you. You can assert or validate some of the things that you place inside it like not specifying a null parameter name like above, or maybe not send null values but a JDBC NULL instead, or whatever...

A map is just a bucket. What you put in is what you get out. Nothing fancy. If your application is simple, few disciplined developers, etc, then a map might be enough.

If you are building a library or if you want to make sure there are some safeties in place, then a Parameter class is better.

1

To ease the tedium of creating the map I'll often write a little utility:. (skeleton code)

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;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.