¿Dónde debe almacenar una aplicación compatible con JDBC sus declaraciones SQL y por qué?
Hasta ahora, logré identificar estas opciones:
- Codificado en objetos comerciales
- Incrustado en cláusulas SQLJ
- Encapsular en clases separadas, por ejemplo, objetos de acceso a datos
- Impulsado por metadatos (desacople el esquema de objeto del esquema de datos; describa las asignaciones entre ellos en metadatos)
- Archivos externos (por ejemplo, archivos de propiedades o recursos)
- Procedimientos almacenados
¿Cuáles son los "pros" y los "contras" de cada uno?
¿Debería considerarse el código SQL "código" o "metadatos"?
¿Deben usarse los procedimientos almacenados solo para optimizar el rendimiento o son una abstracción legítima de la estructura de la base de datos?
¿Es el rendimiento un factor clave en la decisión? ¿Qué pasa con el bloqueo del proveedor ?
¿Qué es mejor: acoplamiento suelto o acoplamiento apretado y por qué?
EDITADO: Gracias a todos por las respuestas, aquí hay un resumen:
Mapeos relacionales de objetos (ORM) impulsados por metadatos
Pros:
- Muy abstracto: el servidor de base de datos se puede cambiar sin necesidad de cambiar el modelo
- Amplia difusión: prácticamente un estándar
- Reduce la cantidad de SQL necesaria
- Puede almacenar SQL en archivos de recursos
- El rendimiento es (generalmente) aceptable
- Enfoque impulsado por metadatos
- (Base de datos) independencia del proveedor
Contras:
- Oculta SQL y las verdaderas intenciones de los desarrolladores
- SQL difícil de ser revisado / cambiado por DBA
- SQL todavía podría ser necesario para casos extraños
- Puede forzar el uso de un lenguaje de consulta propietario, por ejemplo, HQL
- No se presta a la optimización (abstracción)
- Puede carecer de integridad referencial
- Sustituye la falta de conocimiento de SQL o la falta de cuidado para codificar en la base de datos
- Nunca iguale el rendimiento de la base de datos nativa (incluso si se acerca)
- El código del modelo está muy ajustado al modelo de la base de datos
Codificado / encapsulado en la capa DAO
Pros:
- SQL se mantiene en los objetos que acceden a los datos (encapsulación)
- SQL es fácil de escribir (velocidad de desarrollo)
- SQL es fácil de rastrear cuando se requieren cambios
- Solución simple (sin arquitectura desordenada)
Contras:
- SQL no puede ser revisado / cambiado por DBA
- Es probable que SQL se vuelva específico de DB
- SQL puede volverse difícil de mantener
Procedimientos almacenados
Pros:
- SQL mantenido en la base de datos (cerca de los datos)
- SQL es analizado, compilado y optimizado por el DBMS
- SQL es fácil de revisar / cambiar para DBA
- Reduce el tráfico de la red
- Seguridad incrementada
Contras:
- SQL está vinculado a la base de datos (bloqueo del proveedor)
- El código SQL es más difícil de mantener
Archivos externos (por ejemplo, archivos de propiedades o recursos)
Pros
- SQL se puede cambiar sin necesidad de reconstruir la aplicación
- Desacopla la lógica SQL de la lógica empresarial de la aplicación.
- Repositorio central de todas las sentencias SQL: más fácil de mantener
- Más fácil de entender
Contras:
- El código SQL puede volverse imposible de mantener
- Es más difícil verificar el código SQL en busca de errores (de sintaxis)
Incrustado en cláusulas SQLJ
Pros:
- Mejor comprobación de sintaxis
Contras:
- Se vincula demasiado con Java
- Rendimiento más bajo que JDBC
- Falta de consultas dinámicas
- No tan popular
Respuestas:
Por lo general, cuanto más crece la aplicación en términos de tamaño y / o reutilización, mayor es la necesidad de externalizar / abstraer las declaraciones SQL.
Codificado (como constantes finales estáticas) es el primer paso. Almacenado en un archivo (propiedades / archivo xml) es el siguiente paso. Los metadatos impulsados (como lo hace un ORM como Hibernate / JPA) es el último paso.
Hardcoded tiene la desventaja de que es probable que su código se convierta en específico de DB y que debe reescribir / reconstruir / redistribuir en cada cambio. La ventaja es que lo tienes en 1 lugar.
Almacenado en un archivo tiene la desventaja de que puede volverse inmaterial cuando la aplicación crece. La ventaja es que no necesita volver a escribir / reconstruir la aplicación, a menos que necesite agregar un método DAO adicional.
Los metadatos impulsados tienen la desventaja de que el código de su modelo está muy ajustado al modelo de la base de datos. Para cada cambio en el modelo de la base de datos, necesitará reescribir / reconstruir / redistribuir el código. La ventaja es que es muy abstracto y que puede cambiar fácilmente del servidor de base de datos sin la necesidad de cambiar su modelo (pero pregúntese ahora: ¿con qué frecuencia una empresa cambiaría de servidor de base de datos? Probablemente al menos una vez cada 3 años, ¿no? ¿verdad?).
No llamaré a los procedimientos almacenados una "buena" solución para esto. Tienen un propósito completamente diferente. Sin embargo, su código dependería de la base de datos / configuración utilizada.
fuente
No sé si esto es óptimo, pero en mi experiencia terminan codificados (es decir, literales de cadena) en la capa DAO.
fuente
No creo que nadie le dé el desglose de pros / contras que desea, ya que es una pregunta bastante grande. Así que, en cambio, esto es lo que he usado en el pasado y lo que usaré en el futuro.
Yo suelo usar SQL codificado en el DAL. Pensé que esto estaba bien hasta que los DBA quisieron jugar con SQL. Luego tienes que desenterrarlo, formatearlo y enviarlo a los DBA. Quién se reirá de él y lo reemplazará todo. Pero sin los agradables signos de interrogación, o los signos de interrogación en el orden incorrecto y dejar que lo pegue nuevamente en el código Java.
También hemos usado un ORM, y aunque esto es genial para los desarrolladores, nuestros DBA lo odiaban, ya que no hay SQL del que reírse. También usamos un ORM extraño (uno personalizado de un proveedor externo) que tenía la costumbre de matar la base de datos. He usado JPA desde entonces y fue genial, pero lograr que cualquier cosa sea complicada para usarlo más allá de los DBA es una batalla cuesta arriba.
Ahora usamos procedimientos almacenados (con la instrucción de llamada codificada). Ahora, lo primero de lo que todos se quejarán es de que estás atado a la base de datos. Usted está. Sin embargo, ¿con qué frecuencia ha cambiado la base de datos? Sé con certeza que simplemente ni siquiera podríamos intentarlo, la cantidad de otro código que depende de él más el reentrenamiento de nuestros DBA más la migración de los datos. Sería una operación muy cara. Sin embargo, si en su mundo es necesario cambiar las bases de datos en un abrir y cerrar de ojos, es probable que los SP estén fuera.
En el futuro, me gustaría utilizar procedimientos almacenados con herramientas de generación de código para crear clases de Java a partir de paquetes de Oracle.
Editar 2013-01-31 : Unos años y DBA más tarde y ahora usamos Hibernate, yendo a SQL (procesos almacenados en la base de datos) solo cuando sea absolutamente necesario. Creo que esta es la mejor solución. El 99% de las veces, los DB no necesitan preocuparse por el SQL, y el 1% lo hacen en un lugar con el que ya se sienten cómodos.
fuente
Al usar un ORM (como hibernar), es de esperar que no tenga que preocuparse por declaraciones SQL. El rendimiento suele ser aceptable y también obtiene independencia del proveedor.
fuente
Código.
Los procedimientos almacenados permiten la reutilización, incluso dentro de otros procedimientos almacenados. Esto significa que puede hacer un viaje a la base de datos y hacer que ejecute instrucciones de apoyo; la menor cantidad de tráfico es ideal. ORM o sproc, el tiempo en el cable que va a la base de datos y viceversa es algo que no puede recuperar.
ORM no se presta a la optimización debido a su abstracción. IME, ORM también significa una falta de integridad referencial: hace que sea difícil informar de una base de datos. Lo que se guardó en complejidad, ahora se ha incrementado para poder sacar los datos de una manera viable.
No, la simplicidad lo es. El bloqueo del proveedor también ocurre con la base de datos: SQL está relativamente estandarizado, pero todavía hay formas específicas de hacer las cosas.
fuente
El miedo al bloqueo de proveedores en el mundo de Java es interesante.
Espero que no haya pagado $ 50000 por CPU por Oracle Enterprise, y luego solo haya usado el mínimo denominador común para cambiar a Mysql en cualquier momento. Como cualquier buen DBA le dirá, existen diferencias sutiles entre las diferentes bases de datos de renombre, especialmente con respecto a los modelos de bloqueo y cómo logran la coherencia.
Por lo tanto, no tome una decisión sobre cómo implementar sus llamadas SQL basándose únicamente en el principio de SQL independiente del proveedor; tenga una razón real (comercial) para hacerlo.
fuente
SQL dentro de procedimientos almacenados está optimizado por el sistema de base de datos y compilado para mayor velocidad, ese es su hogar natural. SQL es entendido por el sistema de base de datos, analizado por el sistema de base de datos. Mantenga su SQL en la base de datos si puede; envuélvalo en procedimientos o funciones almacenados o cualquier unidad lógica que proporcione el sistema de base de datos, y realice llamadas simples a él utilizando cualquiera de las herramientas que usted o cualquier otra persona haya mencionado.
¿Por qué almacenar código SQL para el sistema de base de datos fuera de la base de datos? A menudo por velocidad de desarrollo. ¿Por qué utilizar el mapeo ORM? - Algunos dicen que el mapeo ORM proporciona compatibilidad entre diferentes sistemas de bases de datos; sin embargo, rara vez en el mundo real una aplicación se aleja de la plataforma de base de datos en la que se creó, especialmente cuando comienza a usar funciones avanzadas como la replicación, y en las raras ocasiones en que sucede que el sistema de base de datos se cambia, se justifica algo de trabajo . Creo que uno de los inconvenientes de ORM es que a menudo sustituye la falta de conocimiento de SQL o la falta de cuidado para codificar en la base de datos. Además, ORM nunca igualará el rendimiento de la base de datos nativa, incluso si se acerca.
Estoy del lado de mantener el código SQL en la base de datos y realizar llamadas simples a él a través de cualquier API o interfaz que desee utilizar. También abstraiga el punto en el que se realizan las llamadas a su base de datos colocando esas llamadas detrás de una clase abstracta o interfaz OO (expresada por métodos), por lo que si alguna vez cambia un nuevo tipo de fuente de datos, será transparente para la capa empresarial .
fuente
La única pregunta que hace que tiene una respuesta definitiva es "¿Es código SQL o metadatos?" Definitivamente es código y, como tal, debe mantenerse en algún tipo de control de código fuente y tener un sistema para actualizar fácilmente a la última versión y revertir cuando no, si las cosas salen mal.
He visto tres formas de hacer SQL en una aplicación y cada una tiene sus pros y sus contras. No existe la mejor manera, pero lo mejor es elegir una que funcione bien con su aplicación y seguir con ella.
fuente
Sucede que usamos el mapeador SQL iBatis, que está más cerca del metal que los ORM como Hibernate. En iBatis, coloca las declaraciones SQL en archivos de recursos (XML), que deben estar en la ruta de clases.
Su lista de enfoques parece bastante completa si agrega la opción ORM de @ ocdecio. Yo diría que usar un ORM y usar un mapeador SQL y archivos de recursos son los dos mejores enfoques. Me mantendría alejado de SQLJ, que no ha tenido mucha aceptación y lo vincula demasiado a Java. También manténgase alejado de los procedimientos almacenados, ya que lo vinculan a un proveedor de base de datos específico (los estándares son casi inexistentes para los procedimientos almacenados).
fuente
Como la mayoría de nosotros, he visto toda la gama, pero debemos considerar SQL como un lenguaje de primera clase. Incluso he visto SQL almacenado en la base de datos que se baja y luego se ejecuta de nuevo.
Los sistemas más exitosos que he visto emplean procedimientos almacenados, funciones y vistas.
Los procesos almacenados mantienen el texto SQL en la base de datos y permiten un cambio relativamente inmediato por parte de aquellos que DESPLIEGAN y PERSONALIZAN (lo que requiere mucho diseño adecuado para admitirlo).
Todas las proyecciones deben ser a través de vistas y selecciones simples por las mismas razones, toda la lógica de proyección debe estar contenida dentro de la vista.
fuente
Sugiero usar DAO con un diseño de fábrica. Entonces, los objetos de ejemplo que necesita serían:
Este estilo superpone la interacción de datos, por lo que solo debería tener que cambiar una capa de código si cambia de base de datos o cambia a tecnologías ORM.
fuente
Realmente no hay ninguna diferencia sustancial entre estos tres:
Supongo que va a incrustar código SQL en forma de cadena directamente en su código Java. Mientras que 1 y 3 probablemente usarán JDBC directamente (o alguna herramienta como Apache DbUtils ), 2 agrega una tecnología de preprocesador a la pila, generando el código JDBC relevante antes de la compilación.
Entonces, esencialmente, si estas soluciones implican incrustar SQL, también puede usar cualquiera de estas tecnologías:
También puede haber otras herramientas que lo ayuden a integrar SQL en Java de una manera más segura que a través de SQLJ o mediante la concatenación de cadenas real.
fuente
Por la experiencia que he tenido, la codificación rígida de declaraciones SQL en los objetos DAO es lo que se usa ampliamente, aunque creo que debería ser el método menos preferido. La mejor práctica debería ser almacenar las declaraciones SQL en un archivo de propiedades. Y obtenga las declaraciones en el objeto DAO a través de una interfaz para archivos de propiedades, digamos java.util.Properties . Las instrucciones sql se pueden intercalar con '?' Para pasar parámetros, a través de un enfoque de instrucción preparada .
Este enfoque ayuda a desacoplar la lógica SQL de la lógica empresarial de la aplicación. Esto hace que esté disponible un repositorio central de todas las declaraciones SQL, lo que facilita la modificación, eliminando la necesidad de buscar declaraciones en la base de datos dentro de la lógica de la aplicación. La comprensión también mejora.
fuente
Los míos terminan en paquetes de recursos. Sé que no es normal, pero es lo más fácil de mantener para mí y para cualquier persona "aparte de mí". Es sencillo y lógico.
De hecho, tengo curiosidad por ver si alguien usa mi enfoque también.
fuente
Como un rexem escribió, las declaraciones SQL son código: deben tratarse como código, no externalizarse (a menos que tenga una buena razón), sino ubicarse con código que procesa datos SQL desde / hacia esas declaraciones. Los ORM / iBatis de framework actuales ofrecen muchas simplificaciones para el desarrollo diario de JDBC.
Algunas respuestas a su pregunta las encontrará en esta pregunta :) El problema de cómo se almacenarán sus declaraciones SQL depende del rey de su aplicación. Cuales son tus necesidades ¿Alta seguridad, facilidad para escribir código o mantenimiento, multiplataforma o bloqueo de proveedor? La siguiente pregunta, ¿necesita un marco SQL puro u ORM será bueno?
Solución más simple (P), difícil de mantener (C)
Mejor verificación de sintaxis (P), falta de consultas dinámicas (C), menor rendimiento que JDBC (C), no tan popular (C)
Debe ser un caso específico que debe hacer eso (C) o si se refiere a ORM (P);)
Fácil de mantener (P) pero más difícil de comprobar si hay errores (C)
Alta seguridad (P), código difícil para mantener los problemas de bloqueo de un proveedor (C)
fuente