Search code examples
javahibernatejpa

What's the cleanest way to chain multiple optional query parameters in Hibernate?


What is the best way to chain multiple optional parameters to a query in hibernate?

Doing something like this feels very clunky, but I don't see a better way to do it:

StringBuilder builder = new StringBuilder("SELECT a from address a WHERE ");
    
if(!StringUtil.isNullOrEmpty(streetName)) {
  builder.append("a.streetName = :streetName AND ");
}
if(!StringUtil.isNullOrEmpty(houseNumber)) {
  builder.append("a.houseNumber = :houseNumber AND ");
}
if(!StringUtil.isNullOrEmpty(city)) {
  builder.append("a.city = :city AND ");
}
if(!StringUtil.isNullOrEmpty(countryCode)) {
  builder.append("a.countryCode = :countryCode AND ");
}
String sql = builder.substring(0, builder.length() - 4); //remove trailing 'AND'
  
TypedQuery<AddressEntity> query = entityManager.createQuery(sql, AddressEntity.class);
 
if(!StringUtil.isNullOrEmpty(streetName)) {
  query.setParameter("streetName", streetName);
}
if(!StringUtil.isNullOrEmpty(houseNumber)) {
  query.setParameter("houseNumber", houseNumber);
}
if(!StringUtil.isNullOrEmpty(city)) {
  query.setParameter("city", city);
}
if(!StringUtil.isNullOrEmpty(countryCode)) {
  query.setParameter("countryCode", countryCode);
}
  
return query.getResultList();

Solution

  • You could use a parameter map...

        private static Map<String, Object> parameters = new HashMap<>();
    
    public static void main(String[] args) {
        parameters.put("streetName", "Linz");
        parameters.put("houseNumber", 1);
        
        String sql = parameters.entrySet().stream().map(e -> "a." + e.getKey() + " = :" + e.getKey()).collect(Collectors.joining(" AND "));
        
        TypedQuery<AddressEntity> query = entityManager.createQuery(sql, AddressEntity.class);
        
        parameters.entrySet().stream().forEach(e -> query.setParameter(e.getKey(), e.getValue()));
        
        return query.getResultList();
    }
    

    }