He estado trabajando en una aplicación de servlet Java que necesita construir declaraciones SQL muy dinámicas para propósitos de informes ad hoc. La función básica de la aplicación es alimentar un montón de parámetros de solicitud HTTP con nombre en una consulta precodificada y generar una tabla de salida con un formato agradable. Utilicé Spring MVC y el marco de inyección de dependencia para almacenar todas mis consultas SQL en archivos XML y cargarlas en la aplicación de informes, junto con la información de formato de la tabla. Con el tiempo, los requisitos de informes se volvieron más complicados que las capacidades de los marcos de mapeo de parámetros existentes y tuve que escribir el mío. Fue un ejercicio interesante de desarrollo y produjo un marco para el mapeo de parámetros mucho más robusto que cualquier otra cosa que pude encontrar.
Las nuevas asignaciones de parámetros se veían así:
select app.name as "App",
${optional(" app.owner as "Owner", "):showOwner}
sv.name as "Server", sum(act.trans_ct) as "Trans"
from activity_records act, servers sv, applications app
where act.server_id = sv.id
and act.app_id = app.id
and sv.id = ${integer(0,50):serverId}
and app.id in ${integerList(50):appId}
group by app.name, ${optional(" app.owner, "):showOwner} sv.name
order by app.name, sv.name
La belleza del marco resultante era que podía procesar los parámetros de solicitud HTTP directamente en la consulta con la verificación de tipo y límite adecuada. No se requieren asignaciones adicionales para la validación de entrada. En la consulta de ejemplo anterior,
se verificaría el parámetro llamado serverId para asegurarse de que pudiera convertirse en un número entero y estuviera en el rango de 0-50. El parámetro appId se procesará como una matriz de números enteros, con un límite de longitud de 50. Si el campo showOwnerestá presente y establecido en "verdadero", los bits de SQL entre comillas se agregarán a la consulta generada para las asignaciones de campos opcionales. field Hay varias asignaciones de tipos de parámetros más disponibles, incluidos segmentos opcionales de SQL con asignaciones de parámetros adicionales. Permite una asignación de consultas tan compleja como se le ocurra al desarrollador. Incluso tiene controles en la configuración del informe para determinar si una consulta determinada tendrá las asignaciones finales a través de un PreparedStatement o simplemente se ejecutará como una consulta prediseñada.
Para los valores de solicitud Http de muestra:
showOwner: true
serverId: 20
appId: 1,2,3,5,7,11,13
Produciría el siguiente SQL:
select app.name as "App",
app.owner as "Owner",
sv.name as "Server", sum(act.trans_ct) as "Trans"
from activity_records act, servers sv, applications app
where act.server_id = sv.id
and act.app_id = app.id
and sv.id = 20
and app.id in (1,2,3,5,7,11,13)
group by app.name, app.owner, sv.name
order by app.name, sv.name
Realmente creo que Spring o Hibernate o uno de esos marcos deberían ofrecer un mecanismo de mapeo más robusto que verifique tipos, permita tipos de datos complejos como matrices y otras características similares. Escribí mi motor solo para mis propósitos, no está del todo leído para el lanzamiento general. Solo funciona con consultas de Oracle en este momento y todo el código pertenece a una gran corporación. Algún día puedo tomar mis ideas y construir un nuevo marco de código abierto, pero espero que uno de los grandes jugadores existentes acepte el desafío.