Programação Java - onde as instruções SQL devem ser armazenadas? [fechadas]

106

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
Adrian
fonte
Boas perguntas, mas talvez um pouco demais para responder todas de uma vez. Levaria algumas páginas para responder a todas essas perguntas: p
NickDK
+1 Boa pergunta! Você deve adicionar "ORM" por @ocdecio. Adicione também "espalhado em todos os lugares em seu código Java" (que eu vi e deve ser o pior).
Jim Ferrans
2
Eu discordo totalmente com "o código SQL é mais difícil de manter" em Stored Procedures. No meu XP, o SQL era mais fácil de manter, uma vez que entrava no banco de dados. Em parte por um motivo usado em arquivos externos (repositório central de todas as instruções SQL - mais fácil de manter), além dos parâmetros são mais fáceis de gerenciar.
Michael Lloyd Lee mlk
1
Na minha opinião, você perdeu uma opção: o uso de visualizações. Você pode expressar SQL complexo em visualizações e então apenas expressar seleções simples nessas visualizações (usando qualquer tipo de abstração: DAO, SQLJ, ORM's, etc). Você terá prós semelhantes aos procedimentos armazenados, mas não acho que você terá nenhum dos contras deles ...
Lukas Eder

Respostas:

31

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.

BalusC
fonte
21

Não sei se isso é o ideal, mas na minha experiência, eles acabam codificados (ou seja, literais de string) na camada DAO.

flybywire
fonte
5
Provavelmente não é o ideal, mas é o que eu também faço. Fácil de escrever, fácil de rastrear e nenhuma arquitetura confusa com que se preocupar.
James Cronen
21
E todo o tempo gasto rastreando o código SQL embutido é a segurança do trabalho. Se você é a única pessoa que sabe onde está o SQL, não pode ser despedido.
S.Lott
11
Sempre me surpreende que muitas pessoas que têm o cuidado de construir um código Java OO limpo e bem arquitetado são as mesmas que toleram escrever SQL confuso e sem desempenho e apenas colocá-lo como strings em lugares aleatórios. Se seu SQL for apenas strings em sua camada DAO, posso garantir que você não tem um DBA em sua equipe. Pelo menos não um bom DBA.
Daniel Pryden
3
-1. Não há problema em ter DAOs, mas no mínimo mova as consultas para um arquivo de propriedades em algum lugar para que um DBA possa revisá-las e ajustá-las conforme apropriado!
cethegeek
3
Minha experiência tem sido, se você estiver fazendo JDBC direto, colocar a string de consulta em uma camada de Objeto de Acesso a Dados é provavelmente a melhor abordagem se você não puder usar uma solução ORM. Uma ressalva é que certifique-se de que todos estejam de acordo com os padrões de codificação para as classes DAO, se você seguir esse caminho. Eu estive com o pacote de recursos e as rotas de procedimento armazenado e ambos têm sido um pesadelo absoluto de manutenção, uma vez que espalha a lógica de acesso a dados em várias camadas, portanto, adicionar uma coluna a uma consulta requer que você altere as coisas em lugares diferentes.
Jason Gritman
12

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.

Michael Lloyd Lee mlk
fonte
1
1 para a ideia de escrever procedimentos armazenados e, em seguida, gerar código Java a partir deles, e não o contrário.
Daniel Pryden
Minha opinião é que a camada Java NÃO deve simular ou mapear de forma alguma a camada de banco de dados. Acho que se você está tentando abstrair o pacote Oracle, faça outro pacote ou mais procedimentos de empacotamento. Eu tento e logicamente separar os dois completamente pela prática.
Jé Queue
2
@Xepoch: Na verdade, concordo - talvez eu devesse ter redigido meu comentário de forma diferente. Seu banco de dados deve ser um reflexo de seu modelo de dados (modelo de relacionamento de entidade) e seu modelo de objeto também deve ser um reflexo de seu modelo de dados (embora não necessariamente idêntico). Portanto, eles devem estar relacionados, pelo menos. Em termos de geração de código Java a partir de procedimentos armazenados, o ponto é que a API para acesso ao seu banco de dados deve ser derivada da estrutura de seu modelo de dados, e não seu modelo de dados derivado da estrutura de seus objetos.
Daniel Pryden
Você pode estar interessado em usar jooq.org . Faz exatamente o que você disse: "geração de código para criar classes Java a partir de pacotes Oracle". Além disso, ele vem com uma DSL semelhante a SQL, semelhante a LINQ em C #, caso você precise expressar SQL em Java, que não pode ser colocado dentro de um procedimento armazenado.
Lukas Eder de
10

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.

Otávio Décio
fonte
13
-1 você terá instruções HQL e a maioria dos problemas permanece em relação ao HQL. Eles estarão dentro do código (literais de string), consultas nomeadas em anotações, consultas nomeadas em arquivos xml, armazenados em arquivos de propriedades?
flybywire
1
@flybywire - com o Hibernate, é uma raridade recorrer ao HQL. Para 98% dos casos, a consulta por exemplo e por critérios (ou seja, usando objetos) é tudo o que é necessário.
SingleShot
2
@SingleShot, não concordo. Se for algo mais complexo do que selecionar por id, acho que é feito com HQL. Eu diria que os critérios e exemplos são usados ​​ao fazer a pesquisa orientada pela interface do usuário, como em uma tela de pesquisa em um catálogo de biblioteca. Mas vamos ver o que os outros pensam.
flybywire
3
@SingleShot - Discordo muito. Usamos muito HQL, especialmente para relatórios de consultas. Alguns recursos HQL não são suportados por critérios (usando funções SQL personalizadas, construtores na cláusula select). O QBE às vezes pode levar a mais problemas do que resolve.
javashlook
4
"Com o Hibernate é uma raridade recorrer ao HQL" é de longe a coisa mais engraçada que já ouvi hoje. QBE é ridículo; e embora você possa ter que recorrer aos critérios para consultas de IU, as consultas bem definidas (relatórios / interação de serviço / etc ...) devem estar todas em HQL.
ChssPly76
10

O código SQL deve ser considerado “código” ou “metadados”?

Código.

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?

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.

O desempenho é um fator chave na decisão? E quanto ao aprisionamento do fornecedor?

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.

Pôneis OMG
fonte
4
1 para chamar o código SQL. Muitas ferramentas ORM tentam ocultar o SQL, quando na verdade costuma ser a melhor linguagem para expressar o que você está tentando fazer. E eu concordo com sua opinião de que stored procedures são melhores que ORM, embora eu duvide que seja uma opinião popular aqui.
Daniel Pryden
9

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.

Hennings
fonte
1
Oh, nada disso! A principal preocupação é permitir que a equipe de suporte altere as instruções SQL (por exemplo, para ajuste, tarefas relacionadas ao DBA) e melhore a visibilidade sobre o que o aplicativo faz (em relação ao banco de dados. A equipe de suporte não tem know-how Java e eles não fique feliz em analisar o código. O aplicativo será uma nova adição a uma grande propriedade dos existentes, todos usando um banco de dados Ingres.
Adrian
6

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 .

John K
fonte
+1 Belo ponto de vista. Você se interessará por esta postagem do blog, eu acho: database-programmer.blogspot.com/2010/12/… .
Lukas Eder de
5

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.

  • ORM - isso reduz a quantidade de SQL que você precisa para escrever e trata de muitos detalhes para você. Você precisará fazer algum SQL customizado. Certifique-se de ter um ORM que lida com isso normalmente.
  • Objetos de acesso a dados - mantém o SQL nos objetos que acessam os dados. Isso encapsula seu banco de dados e faz com que o restante de seu aplicativo não precise saber sobre a estrutura do banco de dados subjacente, apenas a interface para esses objetos.
  • Procedimentos armazenados - isso mantém todo o seu SQL em seu banco de dados e torna mais fácil para seu DBA saber o que está acontecendo. Tudo o que você precisa fazer é fazer com que seu código chame os procs armazenados
Kenny Drobnack
fonte
4

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).

Jim Ferrans
fonte
4

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.

Jé Queue
fonte
1 para mencionar pontos de vista. Isso ainda não está refletido no resumo da pergunta
Lukas Eder,
2

Eu sugiro usar DAOs com um layout de fábrica. Portanto, os objetos de exemplo de que você precisa são:

public class CoolBusinessObject
public class DAOFactory.java
public implementation CoolBusinessOjectDAO
public class CoolBusinessOjectDAOOracleImpl implements CoolBusinessOjectDAO

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.

Jay
fonte
2

Não há realmente nenhuma diferença substancial entre esses três:

  1. Codificado em objetos de negócios
  2. Incorporado em cláusulas SQLJ
  3. Encapsular em classes separadas, por exemplo, objetos de acesso a dados

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:

  • API de critérios JPA , modelando JPQL como uma linguagem específica de domínio interno em Java
  • jOOQ , modelando SQL como uma linguagem específica de domínio interno em Java

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.

Lukas Eder
fonte
1

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.

A máquina
fonte
Algumas pessoas podem objetar que isso introduzirá o risco de injeção de SQL. Qual a sua opinião sobre isso?
Adrian
2
Se você estiver armazenando o código SQL fora do aplicativo de qualquer maneira, qual é a vantagem de armazená-lo como strings em algum lugar em vez de armazená-lo na camada de banco de dados (como procedimentos armazenados)? Os procedimentos armazenados podem fazer uso mais eficaz do otimizador de seu banco de dados, de modo que quase sempre superarão as instruções preparadas.
Daniel Pryden
1
Olá Daniel, não quis dizer, você não escreve procs sql, só quis dizer, você chama os procs armazenados, da maneira que mencionei. Isso ajuda você a ter um melhor controle sobre a passagem de parâmetros para o procedimento armazenado também.
The Machine
1

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.

Brett Ryan
fonte
Curioso por que você não mantém o SQL no banco de dados?
Jé Queue
@Xepoch - O que você quer dizer? As instruções estão em pacotes de recursos (arquivos de propriedades) que estão dentro do mesmo pacote das entidades, portanto, customer.properties está relacionado a Customer.class. Os dados são armazenados no banco de dados.
Brett Ryan
1

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?

* Hardcoded in business objects
* Encapsulate in separate classes e.g. Data Access Objects

Solução mais simples (P), difícil de manter (C)

* Embedded in SQLJ clauses

Melhor verificação de sintaxe (P), falta de consultas dinâmicas (C), desempenho inferior ao de JDBC (C), não tão popular (C)

* Metadata driven (decouple the object schema from the data schema - describe the mappings between them in metadata)

Deve ser um caso específico em que você deve fazer isso (C) ou se você quer dizer ORM (P);)

* External files (e.g. Properties or Resource files)

Fácil de manter (P), mas mais difícil de verificar se há erros (C)

* Stored Procedures

Alta segurança (P), código difícil de manter e problemas de bloqueio de fornecedor (C)

cetnar
fonte