Onde um aplicativo compatível com JDBC deve armazenar suas instruções SQL e por quê?
Até agora, consegui identificar essas opções:
- Codificado em objetos de negócios
- Incorporado em cláusulas SQLJ
- Encapsular em classes separadas, por exemplo, objetos de acesso a dados
- Orientado por metadados (desacoplar o esquema do objeto do esquema de dados - descrever os mapeamentos entre eles nos metadados)
- Arquivos externos (por exemplo, propriedades ou arquivos de recursos)
- Procedimentos armazenados
Quais são os “prós” e “contras” de cada um?
O código SQL deve ser considerado “código” ou “metadados”?
Os procedimentos armazenados devem ser usados apenas para otimização de desempenho ou são uma abstração legítima da estrutura do banco de dados?
O desempenho é um fator chave na decisão? E quanto ao aprisionamento do fornecedor ?
O que é melhor - acoplamento fraco ou acoplamento apertado e por quê?
EDITADO: Obrigado a todos pelas respostas - aqui está um resumo:
Orientado por metadados, ou seja, mapeamentos de objetos relacionais (ORM)
Prós:
- Muito abstrato - o servidor de banco de dados pode ser alternado sem a necessidade de alterar o modelo
- Ampla distribuição - praticamente um padrão
- Reduz a quantidade de SQL necessária
- Pode armazenar SQL em arquivos de recursos
- O desempenho é (geralmente) aceitável
- Abordagem baseada em metadados
- (Banco de dados) independência do fornecedor
Contras:
- Oculta SQL e verdadeiras intenções de desenvolvedores
- SQL difícil de ser revisado / alterado pelo DBA
- SQL ainda pode ser necessário para casos ímpares
- Pode forçar o uso de uma linguagem de consulta proprietária, por exemplo, HQL
- Não se presta à otimização (abstração)
- Pode faltar integridade referencial
- Substitui por falta de conhecimento de SQL ou falta de cuidado para codificar no BD
- Nunca corresponda ao desempenho do banco de dados nativo (mesmo que se aproxime)
- O código do modelo é muito estreitamente acoplado ao modelo de banco de dados
Codificado / encapsulado na camada DAO
Prós:
- O SQL é mantido nos objetos que acessam os dados (encapsulamento)
- SQL é fácil de escrever (velocidade de desenvolvimento)
- SQL é fácil de rastrear quando mudanças são necessárias
- Solução simples (sem arquitetura confusa)
Contras:
- SQL não pode ser revisado / alterado pelo DBA
- É provável que o SQL se torne específico do banco de dados
- SQL pode se tornar difícil de manter
Procedimentos armazenados
Prós:
- SQL mantido no banco de dados (próximo aos dados)
- SQL é analisado, compilado e otimizado pelo DBMS
- O SQL é fácil para o DBA revisar / alterar
- Reduz o tráfego de rede
- Maior segurança
Contras:
- O SQL está vinculado ao banco de dados (dependência do fornecedor)
- O código SQL é mais difícil de manter
Arquivos externos (por exemplo, propriedades ou arquivos de recursos)
Prós
- O SQL pode ser alterado sem a necessidade de reconstruir o aplicativo
- Separa a lógica SQL da lógica de negócios do aplicativo
- Repositório central de todas as instruções SQL - mais fácil de manter
- Mais fácil de entender
Contras:
- O código SQL pode se tornar impossível de manter
- Mais difícil de verificar se há erros (de sintaxe) no código SQL
Incorporado em cláusulas SQLJ
Prós:
- Melhor verificação de sintaxe
Contras:
- Ligações muito próximas de Java
- Desempenho inferior ao JDBC
- Falta de consultas dinâmicas
- Não tão popular
Respostas:
Normalmente, quanto mais o aplicativo cresce em termos de tamanho e / ou capacidade de reutilização, mais é necessário externalizar / abstrair as instruções SQL.
Codificado (como constantes finais estáticas) é a primeira etapa. Armazenado em um arquivo (propriedades / arquivo xml) é a próxima etapa. Orientado por metadados (como feito por um ORM como Hibernate / JPA) é a última etapa.
Hardcoded tem a desvantagem de que seu código provavelmente se tornará específico do banco de dados e você precisará reescrever / reconstruir / redistribuir em cada alteração. A vantagem é que você o tem em um só lugar.
Armazenado em um arquivo tem a desvantagem de se tornar impossível de manter quando o aplicativo crescer. A vantagem é que você não precisa reescrever / reconstruir o aplicativo, a menos que precise adicionar um método DAO extra.
Orientado por metadados tem a desvantagem de que seu código de modelo é muito estreitamente acoplado ao modelo de banco de dados. Para cada mudança no modelo de banco de dados, você precisará reescrever / reconstruir / redistribuir o código. A vantagem é que ele é muito abstrato e você pode facilmente alternar do servidor de banco de dados sem a necessidade de alterar seu modelo (mas pergunte-se agora: com que freqüência uma empresa mudaria de servidor de banco de dados? Provavelmente pelo menos apenas uma vez a cada 3 anos, não é? não é?).
Não chamarei procedimentos armazenados uma solução "boa" para isso. Eles têm um propósito totalmente diferente. Mesmo assim, seu código seria dependente do banco de dados / configuração usada.
fonte
Não sei se isso é o ideal, mas na minha experiência, eles acabam codificados (ou seja, literais de string) na camada DAO.
fonte
Eu não acho que ninguém vai te dar a divisão de pró / contra que você deseja, pois é uma questão bastante ampla. Em vez disso, aqui está o que usei no passado e o que usarei no futuro.
Eu costumo usar SQL codificado na DAL. Achei que estava tudo bem até que os DBAs quisessem brincar com o SQL. Em seguida, você tem que desenterrá-lo, formatá-lo e enviá-lo aos DBAs. Quem vai rir disso e substituir tudo. Mas sem os bons pontos de interrogação, ou os pontos de interrogação na ordem errada e deixá-lo recolocar no código Java.
Também usamos um ORM e, embora seja ótimo para desenvolvedores, nossos DBAs odiaram, pois não há SQL para eles rirem. Também usamos um ORM ímpar (um personalizado de um fornecedor terceirizado) que tinha o hábito de matar o banco de dados. Eu usei o JPA desde então e foi ótimo, mas tornar qualquer coisa complicada de usá-lo além dos DBAs é uma batalha difícil.
Agora usamos Stored Procedures (com a instrução call codificada). Agora, a primeira coisa de que todos reclamarão é que você está preso ao banco de dados. Tu es. No entanto, com que frequência você mudou o banco de dados? Eu sei que simplesmente não poderíamos nem tentar, a quantidade de outro código dependente dele, além de retreinar nossos DBAs e migrar os dados. Seria uma operação muito cara. No entanto, se em seu mundo mudar os bancos de dados rapidamente é necessário, os SPs provavelmente estão fora de questão.
No futuro, gostaria de usar procedimentos armazenados com ferramentas de geração de código para criar classes Java a partir de pacotes Oracle.
Edite 31/01/2013 : Alguns anos e DBAs depois e agora usamos Hibernate, indo para SQL (procs armazenados no banco de dados) apenas quando absolutamente necessário. Acho que essa é a melhor solução. 99% das vezes os bancos de dados não precisam se preocupar com o SQL, e o 1% que o fazem está em um lugar com o qual já se sentem confortáveis.
fonte
Ao usar um ORM (como hibernação) esperamos que você vai ter nenhum instruções SQL que se preocupar. O desempenho é geralmente aceitável e você também obtém independência do fornecedor.
fonte
Código.
Os procedimentos armazenados permitem a reutilização, inclusive dentro de outros procedimentos armazenados. Isso significa que você pode fazer uma viagem ao banco de dados e fazer com que ele execute as instruções de apoio - o mínimo de tráfego é o ideal. ORM ou sproc, o tempo na transmissão indo para o db & back é algo que você não pode recuperar.
ORM não se presta à otimização por causa de sua abstração. IME, ORM também significam falta de integridade referencial - dificultam o relato de um banco de dados. O que foi economizado em complexidade, agora aumentou para ser capaz de extrair os dados de uma maneira viável.
Não, a simplicidade é. O bloqueio do fornecedor também ocorre com o banco de dados - o SQL é relativamente padronizado, mas ainda existem maneiras específicas do fornecedor de fazer as coisas.
fonte
O medo de ficar preso a um fornecedor no mundo java é interessante.
Espero que você não tenha pago $ 50000 por CPU pelo Oracle Enterprise, e então tenha usado apenas o mínimo denominador comum para mudar para o Mysql a qualquer minuto. Como qualquer bom DBA irá lhe dizer, existem diferenças sutis entre os diferentes bancos de dados de grandes nomes, especialmente com relação aos modelos de bloqueio e como eles alcançam consistência.
Portanto, não tome uma decisão sobre como implementar suas chamadas de SQL apenas com base no princípio do SQL agnóstico de fornecedor - tenha um motivo real (comercial) para fazer isso.
fonte
SQL dentro de Stored Procedures é otimizado pelo sistema de banco de dados e compilado para velocidade - esse é seu lar natural. SQL é compreendido pelo sistema de banco de dados, analisado pelo sistema de banco de dados. Mantenha seu SQL no banco de dados, se puder; envolva-o em procedimentos armazenados ou funções ou quaisquer unidades de lógica que o sistema de banco de dados forneça e faça chamadas simples para ele usando qualquer uma das ferramentas que você ou qualquer outra pessoa mencionou.
Por que armazenar o código SQL para o sistema de banco de dados fora do banco de dados? Freqüentemente, para velocidade de desenvolvimento. Por que usar o mapeamento ORM? - Alguns dizem que o mapeamento ORM fornece compatibilidade entre diferentes sistemas de banco de dados; no entanto, raramente no mundo real um aplicativo sai da plataforma de banco de dados sobre a qual foi criado, especialmente quando começa a usar recursos avançados como replicação e, nas raras ocasiões em que acontece que o sistema de banco de dados é trocado, algum trabalho é garantido . Eu acredito que uma das desvantagens do ORM, muitas vezes substitui a falta de conhecimento de SQL ou a falta de cuidado com o código no banco de dados. Além disso, o ORM nunca corresponderá ao desempenho do banco de dados nativo, mesmo se chegar perto.
Estou evitando manter o código SQL no banco de dados e fazer chamadas simples para ele por meio de qualquer API ou interface que você deseja usar. Também abstraia o ponto em que suas chamadas de banco de dados são feitas, colocando essas chamadas atrás de uma classe abstrata ou interface OO (expressa por métodos), então, se você trocar um novo tipo de fonte de dados, será transparente para a camada de negócios .
fonte
A única pergunta que você faz com uma resposta definitiva é "É código SQL ou metadados?" É definitivamente um código e, como tal, deve ser mantido em algum tipo de controle de código-fonte e ter um sistema para atualizar facilmente para a versão mais recente e reverter quando não, se as coisas derem errado.
Já vi três maneiras de fazer SQL em um aplicativo e cada uma tem seus prós e contras. Não existe a melhor maneira, mas a melhor coisa é escolher uma que funcione bem com seu aplicativo e ficar com ela.
fonte
Acontece que usamos o mapeador SQL iBatis, que é mais próximo do metal do que ORMs como o Hibernate. No iBatis, você coloca as instruções SQL em arquivos de recursos (XML), que precisam estar no classpath.
Sua lista de abordagens parece bastante abrangente se você adicionar a opção ORM de @ocdecio. Eu diria que usar um ORM e usar um mapeador SQL e arquivos de recursos são as duas melhores abordagens. Eu me afastaria do SQLJ, que não teve muita aceitação e liga você muito estreitamente ao Java. Além disso, fique longe de procedimentos armazenados, pois eles o prendem a um fornecedor de banco de dados específico (os padrões são quase inexistentes para procedimentos armazenados).
fonte
Como a maioria de nós, eu vi toda a gama, mas precisamos considerar SQL uma linguagem de primeira classe. Eu até vi SQL armazenado no banco de dados que é puxado para baixo e executado de volta.
Os sistemas mais bem-sucedidos que já vi empregam procedimentos armazenados, funções e visualizações.
Os procs armazenados mantêm o texto SQL de volta no banco de dados e permitem mudanças relativamente imediatas por parte de IMPLEMENTAÇÃO e PERSONALIZAÇÃO (o que requer muito design adequado para suportá-lo).
Todas as projeções devem ser por meio de visualizações e seleções simples pelos mesmos motivos, toda a lógica de projeção deve estar contida na visualização.
fonte
Eu sugiro usar DAOs com um layout de fábrica. Portanto, os objetos de exemplo de que você precisa são:
Este estilo coloca em camadas a interação de dados, então você só deve ter que mudar uma camada de código se mudar de banco de dados ou mudar para tecnologias ORM.
fonte
Não há realmente nenhuma diferença substancial entre esses três:
Estou assumindo que você irá incorporar o código SQL em um formato de string diretamente no seu código Java. Enquanto 1 e 3 provavelmente usarão JDBC diretamente (ou alguma ferramenta como Apache DbUtils ), 2 adiciona uma tecnologia de pré-processador à pilha, gerando o código JDBC relevante antes da compilação.
Então, essencialmente, se essas soluções envolvem a incorporação de SQL, você também pode usar qualquer uma destas tecnologias:
Também pode haver outras ferramentas para ajudá-lo a incorporar SQL em Java de uma maneira mais segura de tipos do que por meio de SQLJ ou por meio de concatenação de string real.
fonte
De acordo com a minha experiência, a codificação de instruções sql nos objetos DAO é o que é amplamente usado, embora eu acho que deve ser o método menos preferido. A melhor prática deve ser armazenar as instruções sql em um arquivo de propriedades. E obtenha as instruções no objeto DAO por meio de uma interface para arquivos de propriedades, digamos java.util.Properties . As instruções sql podem ser intercaladas com '?' S para passar parâmetros, por meio de uma abordagem de instrução preparada .
Essa abordagem ajuda a desacoplar a lógica sql da lógica de negócios do aplicativo. Isso disponibiliza um repositório central de todas as instruções sql, o que torna a modificação mais fácil, eliminando a necessidade de pesquisar as instruções do banco de dados na lógica do aplicativo. A compreensibilidade também melhora.
fonte
Os meus acabam em pacotes de recursos. Eu sei que não é normal, mas é o mais fácil para mim e qualquer pessoa "além de mim" manter. É simples e lógico.
Na verdade, estou curioso para ver se alguém usa minha abordagem também.
fonte
Como um rexem escreveu, as instruções SQL são códigos - elas devem ser tratadas como código, não externalizadas (a menos que você tenha um bom motivo), mas colocadas com código que processa dados SQL de / para essas instruções. O framework de ORMs / iBatis de hoje oferece muitas simplificações para o desenvolvimento JDBC do dia-a-dia.
Algumas respostas à sua pergunta você encontrará nesta pergunta :) O problema de como suas instruções SQL serão armazenadas depende do tipo de aplicativo. Quais são suas necessidades? Alta segurança, facilidade de escrever código ou manutenção, plataforma cruzada ou dependência de fornecedor? A próxima pergunta você precisa de um framework SQL ou ORM puro será bom?
Solução mais simples (P), difícil de manter (C)
Melhor verificação de sintaxe (P), falta de consultas dinâmicas (C), desempenho inferior ao de JDBC (C), não tão popular (C)
Deve ser um caso específico em que você deve fazer isso (C) ou se você quer dizer ORM (P);)
Fácil de manter (P), mas mais difícil de verificar se há erros (C)
Alta segurança (P), código difícil de manter e problemas de bloqueio de fornecedor (C)
fonte