Implementação de Herança em BD relacional

Olá…
Estou trabalhando com inferências sobre dados em Bancos de dados relacionais.
Minhas inferências dão origem a grafos, que também são armazenados no BD e carregados na aplicação quando a inferência é iniciada.

o grafo que quero armazenar no BD no momento, representa átomos lógicos conectados por conectivos lógicos (no momento apenas AND e OR). Assim, meu grafo tem origem em um conjunto de nodos inter-relacionados, onde cada nodo pode ser um átomo lógico ou um conectivo lógico. Pensei nas seguintes tabelas para armazenar o grafo:

->Nodo
int ID: identificador

->Nodo_Atomo_Logico
int ID: identificador
int ID_Polaridade: faz referência à polaridade do átomo (se é uma afirmação ou uma negação). Referência à tabela Tipo_Polaridade

->Nodo_Conectivo_logico
int ID: identificador
int ID_Conectivo: faz referência a um tipo de conectivo (AND ou OR, neste caso). Referência à tabela Tipo_Conectivo

->Aresta
int ID_Pai: identificador do nodo pai. Faz referência à tabela Nodo
int ID_Filho: identificador do nodo filho. Faz referência à tabela Nodo

Como podem ver, “Nodo_Atomo_Logico” e “Nodo_Conectivo_Logico” precisariam ser especializações de “Nodo”. Sempre que eu inserisse um registro de um destes dois tipos, seria inserido um registro em Nodo. É preciso fazer esta modelagem para manter uma normalização na modelagem da Aresta, porque arestas podem ser estabelecidas entre dois nodos de qualquer tipo.

Queria saber como posso implementar esta herança em um banco de dados relacional. Estou usando o Oracle 10g XE em meus testes.

Não conheço o Oracle para dizer se há recursos que tornem mais direta a utilização de herança. Segue uma dica sem considerar que tipo de banco relacional é:

  • Na tabela Nodo colocar uma coluna que identifique se o nó pertence à tabela Nodo_Atomo_Logico ou Nodo_Conectivo_logico.

Att.

[quote=Jokabeludoido]Olá…
Estou trabalhando com inferências sobre dados em Bancos de dados relacionais.
Minhas inferências dão origem a grafos, que também são armazenados no BD e carregados na aplicação quando a inferência é iniciada.

o grafo que quero armazenar no BD no momento, representa átomos lógicos conectados por conectivos lógicos (no momento apenas AND e OR). Assim, meu grafo tem origem em um conjunto de nodos inter-relacionados, onde cada nodo pode ser um átomo lógico ou um conectivo lógico. Pensei nas seguintes tabelas para armazenar o grafo:

->Nodo
int ID: identificador

->Nodo_Atomo_Logico
int ID: identificador
int ID_Polaridade: faz referência à polaridade do átomo (se é uma afirmação ou uma negação). Referência à tabela Tipo_Polaridade

->Nodo_Conectivo_logico
int ID: identificador
int ID_Conectivo: faz referência a um tipo de conectivo (AND ou OR, neste caso). Referência à tabela Tipo_Conectivo

->Aresta
int ID_Pai: identificador do nodo pai. Faz referência à tabela Nodo
int ID_Filho: identificador do nodo filho. Faz referência à tabela Nodo

Como podem ver, “Nodo_Atomo_Logico” e “Nodo_Conectivo_Logico” precisariam ser especializações de “Nodo”. Sempre que eu inserisse um registro de um destes dois tipos, seria inserido um registro em Nodo. É preciso fazer esta modelagem para manter uma normalização na modelagem da Aresta, porque arestas podem ser estabelecidas entre dois nodos de qualquer tipo.

Queria saber como posso implementar esta herança em um banco de dados relacional. Estou usando o Oracle 10g XE em meus testes.[/quote]

Há basicamente três soluções para herança em BD relacional

  1. Uma tabela para toda a hierarquia de classe. É a solução proposta pelo Adelar. Você teria uma única tabela:
    ->Nodo
    int ID: identificador
    byte TIPO: indica à que classe pertence
    int ID_Polaridade: faz referência à polaridade do átomo (se é uma afirmação ou uma negação). Referência à tabela Tipo_Polaridade
    int ID_Conectivo: faz referência a um tipo de conectivo (AND ou OR, neste caso). Referência à tabela Tipo_Conectivo

Vantagens: simplicidade de implementação e facilidade no acesso aos dados
Desvantagens: Alto acoplamento;

  1. Uma tabela por classe concreta: Você teria 2 tabelas

->Nodo_Atomo_Logico
int ID: identificador
int ID_Polaridade: faz referência à polaridade do átomo (se é uma afirmação ou uma negação). Referência à tabela Tipo_Polaridade

->Nodo_Conectivo_logico
int ID: identificador
int ID_Conectivo: faz referência a um tipo de conectivo (AND ou OR, neste caso). Referência à tabela Tipo_Conectivo

Vantagens: Implementação fácil e menor acoplamento que a primeira abordagem
Desvantagens: Baixo suporte a polimorfismo. Caso você precise realizar um select de todos os nodos, terá que contar com metadados

  1. Uma tabela por classe: Você teria 3 tabelas
    ->Nodo
    int ID: identificador

->Nodo_Atomo_Logico
int ID: identificador
int ID_Polaridade: faz referência à polaridade do átomo (se é uma afirmação ou uma negação). Referência à tabela Tipo_Polaridade

->Nodo_Conectivo_logico
int ID: identificador
int ID_Conectivo: faz referência a um tipo de conectivo (AND ou OR, neste caso). Referência à tabela Tipo_Conectivo

Vantagens: Baixo acoplamento, alto suporte a polimorfismo e é o mais aderente à OO
Desvantagem: Implementação difícil e busca de informação menos eficiente.

Abraços

Em termos de modelagem você já tem o suficiente. O que você precisa fazer é que ID nas tabelas filhas seja uma FK (chave estrangeira) para a tabela pai, no caso, nodo. Assim, você deve inserir primeiro um registro em Nodo para depois inserí-lo em uma das tabelas filhas. Você pode automatizar o processo através de triggers, mas eu particularmente evito usá-las. O fato é que sempre que você faz um mapeamento objeto->relacional você acabe perdendo poder de abstração.

Pois é…Eu não tenho muita experiência com BD´s. É a primeira vez que me deparo com um problema em que a herança se faz tão presente. Achei a herança útil neste caso porque o polimorfismo é útil aqui, senão a modelagem de aresta me parece ficar contra-intuitiva.
Deixa ver se entendi:
Os ID´s das tabelas filhas seriam primárias e estrangeiras, apontando para ID na tabela pai? E para manter consistente eu precisaria antes adicionar um registro na tabela pai e depois na tabela filha correspondente?

Exato

[quote=JokabeludoidoPois é…Eu não tenho muita experiência com BD´s. É a primeira vez que me deparo com um problema em que a herança se faz tão presente. Achei a herança útil neste caso porque o polimorfismo é útil aqui, senão a modelagem de aresta me parece ficar contra-intuitiva.
Deixa ver se entendi:
Os ID´s das tabelas filhas seriam primárias e estrangeiras, apontando para ID na tabela pai? E para manter consistente eu precisaria antes adicionar um registro na tabela pai e depois na tabela filha correspondente?[/quote]

Você não tem como usar um JPA (Hibernate)?

[quote=luizSC][quote=JokabeludoidoPois é…Eu não tenho muita experiência com BD´s. É a primeira vez que me deparo com um problema em que a herança se faz tão presente. Achei a herança útil neste caso porque o polimorfismo é útil aqui, senão a modelagem de aresta me parece ficar contra-intuitiva.
Deixa ver se entendi:
Os ID´s das tabelas filhas seriam primárias e estrangeiras, apontando para ID na tabela pai? E para manter consistente eu precisaria antes adicionar um registro na tabela pai e depois na tabela filha correspondente?
Você não tem como usar um JPA (Hibernate)?[/quote]

E o que impede de usar JPA ?

[quote=Javart][quote=luizSC][quote=JokabeludoidoPois é…Eu não tenho muita experiência com BD´s. É a primeira vez que me deparo com um problema em que a herança se faz tão presente. Achei a herança útil neste caso porque o polimorfismo é útil aqui, senão a modelagem de aresta me parece ficar contra-intuitiva.
Deixa ver se entendi:
Os ID´s das tabelas filhas seriam primárias e estrangeiras, apontando para ID na tabela pai? E para manter consistente eu precisaria antes adicionar um registro na tabela pai e depois na tabela filha correspondente?
Você não tem como usar um JPA (Hibernate)?[/quote]

E o que impede de usar JPA ?[/quote]

Em primeiro lugar, porque tenho ainda menos experiência com JPA. Em segundo, porque estou trabalhando sobre um código que não é meu, que já faz toda a manipulação de objetos e persistência deles, usando DAO´s. O código é gigantesco e o banco de dados tem algumas centenas de tabelas. Este grafo que estou implementando é relativamente isolado, mas faz um tipo de meta-referência à outras tabelas, colunas e valores do BD. Os nodos que representam átomos lógicos irão armazenar também um nome de tabela, um nome de coluna desta tabela e um valor, por exemplo. A partir deste modelo em grafo farei análises de certos registros para realizar interpretação simbólica. Ou seja, eu preciso ter acesso à todo o BD de forma flexível, sem muita abstração no caminho, mas, ao mesmo tempo, gostaria de implementar esta abstrção de herança. Acho até que vou seguir o conselho do colega acima. Me pareceu um bom modo de fazer isso.

Obrigado a todos.

[quote]
Em primeiro lugar, porque tenho ainda menos experiência com JPA. Em segundo, porque estou trabalhando sobre um código que não é meu, que já faz toda a manipulação de objetos e persistência deles, usando DAO´s. [/quote]

Esse modelo é totalmente standAlone ou tem várias camadas ?

[quote]
O código é gigantesco e o banco de dados tem algumas centenas de tabelas. [/quote]

Você se utiliza de alguma ferramenta tipo DRIVER MODEL, algo como MDA ?

[quote]
Este grafo que estou implementando é relativamente isolado, mas faz um tipo de meta-referência à outras tabelas, colunas e valores do BD. Os nodos que representam átomos lógicos irão armazenar também um nome de tabela, um nome de coluna desta tabela e um valor, por exemplo. A partir deste modelo em grafo farei análises de certos registros para realizar interpretação simbólica.[/quote]

A Situação é um grafo que use um mecanismo de herença isso é relacionado ao que você quer como o DAO funcione ?

[quote]
Ou seja, eu preciso ter acesso à todo o BD de forma flexível, sem muita abstração no caminho, mas, ao mesmo tempo, gostaria de implementar esta abstrção de herança. Acho até que vou seguir o conselho do colega acima. Me pareceu um bom modo de fazer isso.
Obrigado a todos.[/quote]

É uma persistencia com SQL puro ?

[quote=Javart][quote]
Em primeiro lugar, porque tenho ainda menos experiência com JPA. Em segundo, porque estou trabalhando sobre um código que não é meu, que já faz toda a manipulação de objetos e persistência deles, usando DAO´s. [/quote]

Esse modelo é totalmente standAlone ou tem várias camadas ?
[/quote]

Standalone no sentido de independente? Sim, é standalone neste sentido. Mas ele prevê estensões e outros módulos plugáveis…Prefiro não botar a mão em cõdigo que não é meu, em outras palavras. Vou apenas desenvolver um outro módulo para este software, que fará inferências sobre o banco de dados que ele usa.

[quote][quote]
O código é gigantesco e o banco de dados tem algumas centenas de tabelas. [/quote]

Você se utiliza de alguma ferramenta tipo DRIVER MODEL, algo como MDA ?
[/quote]

Não, que eu saiba não uso. Até porque não sei exatamente o que esta sopa de letrinhas significa :oops:

[quote][quote]
Este grafo que estou implementando é relativamente isolado, mas faz um tipo de meta-referência à outras tabelas, colunas e valores do BD. Os nodos que representam átomos lógicos irão armazenar também um nome de tabela, um nome de coluna desta tabela e um valor, por exemplo. A partir deste modelo em grafo farei análises de certos registros para realizar interpretação simbólica.[/quote]

A Situação é um grafo que use um mecanismo de herença isso é relacionado ao que você quer como o DAO funcione ?
[/quote]

Estes grafos modelarão as inferências lógicas sobre o BD. Eles serão trazidos à memória para o processo de inferência. No momento, em fase de testes, estou persistindo e recuperando via SQL puro e direto, mas pretendo usar DAO´s para a versão final, para manter o padrão com o restante do sistema.

[quote][quote]
Ou seja, eu preciso ter acesso à todo o BD de forma flexível, sem muita abstração no caminho, mas, ao mesmo tempo, gostaria de implementar esta abstrção de herança. Acho até que vou seguir o conselho do colega acima. Me pareceu um bom modo de fazer isso.
Obrigado a todos.[/quote]

É uma persistencia com SQL puro ?
[/quote]

Sim, todo o sistema usa SQL puro, mas usa DAO´s para abstrair a persistência.

Se vc nao vai botar a mao no codigo , vai ter que usar o modelo pra que o comportamento do codigo possa a continuar por inferencia ao banco de dados mas as entidades do modelo antigo nao estariam ja no DB, vai desvia-la pra um modelo novo de que forma iria invocar.E o modelo antigo que garantias vc vai ter que ele nao vai gerar colisao de dados com o seu por inferencia.

:arrow: FONTE www.agilemodeling.com/essays/mda.htm

The Model-Driven Architecture (MDA) defines an approach to modeling that separates the specification of system functionality from the specification of its implementation on a specific technology platform. In short it defines a guidelines for structuring specifications expressed as models. The MDA promotes an approach where the same model specifying system functionality can be realized on multiple platforms through auxiliary mapping standards, or through point mappings to specific platforms. It also supports the concept of explicitly relating the models of different applications, enabling integration and interoperability and supporting system evolution as platform technologies come and go.

[quote]
Este grafo que estou implementando é relativamente isolado, mas faz um tipo de meta-referência à outras tabelas, colunas e valores do BD. Os nodos que representam átomos lógicos irão armazenar também um nome de tabela, um nome de coluna desta tabela e um valor, por exemplo. A partir deste modelo em grafo farei análises de certos registros para realizar interpretação simbólica.[/quote]
A linguagem que o seu grafo esta utilizando e Java.

No DAO aqui vc quer usar como Interface separando responsabilidade do comportamento do Modelo.

[quote]
Ou seja, eu preciso ter acesso à todo o BD de forma flexível, sem muita abstração no caminho, mas, ao mesmo tempo, gostaria de implementar esta abstrção de herança. Acho até que vou seguir o conselho do colega acima. Me pareceu um bom modo de fazer isso.
Obrigado a todos.[/quote]
Se utilizar a abstracao vai ter que ter uma dinamicidade maior o que vai ter que utilizar um desenvolvimento orientado a dominio e vai ter que abandonar o conceito fisico desjado por grafos sobre inferencia vai ter que usar um pattern que por via reflection faca persistencia ao modelo plugavel.

[quote]
Sim, todo o sistema usa SQL puro, mas usa DAO´s para abstrair a persistência.[/quote]
Vai ter quer anotar entidades para ter acesso ao DAO que tenha esse aspecto desejado.

Meus grafos ficarão no mesmo BD que o restante da aplicação…Como eu disse, eu estou pensando em usar uma tabela para fazer meta-referência. Esta tabela vai mapear tabelas, colunas e valores do BD já estabelecido para certos atributos dos nodos lógicos do meu grafo.

Estou implementando o sistema de inferência em Java e armazenando eles no mesmo BD da aplicação, só que em um modelo relativamente independente do restante.

Pretendo usar dao´s para isso sim…Mas, no momento, estou trabalhando com SQL, para fazer alguns testes.

Acho que não vou precisar usar reflection.

Eu criei o BD para armazenar aquele modelo de grafos que eu falei antes. No entanto, estou tendo problemas para armazenar meus nodos filhos do Nodo no banco de dados.

Quando eu tento inserir um NODO_ATOMO_LOGICO, surge o seguinte erro:

java.sql.SQLException: ORA-00984: coluna não permitida aqui

Estou enviando o SQL da criação do banco em Oracle. Se alguém puder me dizer o que pode estar acontecendo, ficaria grato.