Uso de una sentencia preparada y un enlace de variable Order By en Java con el controlador JDBC

Estoy usando

  1. jdbcTemplate para hacer conexiones JDBC a una base de datos mySQL
  2. declaraciones preparadas para protegerme tanto como sea posible de los ataques de inyección de SQL
  3. con la necesidad de aceptar solicitudes del usuario para ordenar los datos en cualquiera de una docena de columnas diferentes
  4. la siguiente statement

    jdbcTemplate.query("SELECT * FROM TABLE1 ORDER BY ? ?", colName, sortOrder); 

Por supuesto, esto no funciona, porque no se supone que los enlaces de variables especifiquen nombres de columnas, solo valores de parámetros para expresiones en la consulta.

Entonces … ¿cómo está la gente resolviendo este problema? Solo hacer el ordenamiento en código Java parece una solución fácil, pero dado que obtengo una cadena variable para la columna para ordenar, y una variable que me dice el orden de clasificación … esa es una cantidad fea de condiciones de comparación para cubrir. Parece que debería ser un problema común con un patrón común para resolverlo …

? Placeholders ? solo se puede usar para valores de parámetros, pero no con instrucciones de columna y orden de clasificación. Así que la forma estándar de hacer esto como se señala, por ejemplo, aquí es usar el formato String # () o algo similar para agregar el nombre de su columna y el valor del pedido a su consulta.

Otra opción es usar Spring Data JPA, donde puede asignar a su método como argumento una instancia de tipo Sort que contenga toda la información necesaria para que la base de datos la ordene.

Me gustaría concatenar el nombre de la columna y el orden de la consulta SQL, pero solo después

  1. verificar que el nombre y el orden de la columna sean válidos en este contexto.
  2. desinfectándolos para contrarrestar cualquier bash de ataque de inyección SQL .

Creo que esto es eficiente en comparación con buscar los resultados en la capa de aplicación y ordenarlos aquí.

Mi sugerencia es la asignación de claves y columnas. Es una solución segura .

Al principio, iniciamos nuestro mapa de la manera más simple posible. Para mayor comodidad, sobrecargué el método get (clave Obiect) para devolver la columna predeterminada (“fullName”) en caso de error. Esto protegerá contra SqlExeption.

  static Map sortCol; { sortCol = new HashMap(){ {//Enter all data for mapping put("name","fullName"); put("rok","year"); put("rate","likes"); put("count-rate","countRate"); } /** * * @param key for column name * @return column name otherwise default "fullName" */ @Override public String get(Object key) { String col =super.get(key); return null==col?"fullName":col; } }; } 

Aquí hay un ejemplo simple de uso.

 String sqlQuery= "Select \"fullName\",year,likes,count-rate, country ..."+ "from blaBla..."+ "where blaBla..."+ "order by "+sortCol.get("keySort") "\n"; // keySort can have the value name, count-rate etc .. 

Por cierto, nunca deberías revelar los nombres reales de las columnas en las interfaces de usuario, como REST o SOAP, etc. Para el atacante, es una gran ayuda.