02
Programação orientada a objetos e banco de dados relacional: como mapear dependências, agregações, composições e heranças
Filed Under (Banco de dados) by Antonio Passos on 02-03-2009
Tagged Under : Banco de dados, banco de dados relacional, Mapeamento objeto-relacional, Modelagem de dados, modelo relacional
A questão é antiga, a resposta, conhecida, mas ainda assim atormenta estudantes de programação orientada a objetos e mesmo profissionais TI: como fazer o mapeamento das relações complexas (como dependência, agregação, composição e herança) entre os objetos de um programa orientado a objetos para bancos de dados relacionais, os quais armazenam dados em linhas e colunas de tabelas que mantêm ligações lógicas entre si pela utilização de chaves estrangeiras?
A solução, sabemos, para o armazenamento de objetos em bancos de dados relacionais passa pela adoção de técnicas de mapeamento objeto-relacional vista neste artigo.
Considere o diagrama de classes abaixo (clique na imagem para visualizá-la em tamanho maior):
Trata-se do diagrama de classes de um hipotético aplicativo (JPratosProntos) que registra pedidos de refeições (pratos) por telefone:
Que tipos de relacionamentos vemos ali? São eles:
- Relacionamentos de dependência entre:
- Pedido e Cliente;
- Pedido e Funcionario
- Prato e ItemDoPedido
- Relacionamentos de composição entre:
- Pessoa e Endereco;
- Pessoa e Telefone
- Pessoa e Email;
- Pedido e ItemDoPedido
- Relacionamento de agregação entre
- Prato e Fornecedor
- Relacionamentos de herança entre
- Pessoa e PessoaFisica;
- Pessoa e PessoaJuridica;
- PessoaFisica e Cliente;
- PessoaFisica e Funcionario
Uma vez que esses objetos e suas relações tenham que ser armazenados em um banco de dados relacional (por exemplo, no H2), como seria o modelo físico desse banco de dados? Abaixo, uma solução possível (clique na imagem para visualizá-la em tamanho maior):
Analise como foram feitos os mapeamentos. Por exemplo:
- O mapeamento do relacionamento de dependência entre as classes Pedido e Cliente foi feito para uma chave estrangeira (FK) na tabela Pedido que aponta para a chave primária (codcliente) da tabela Cliente.
- O relacionamento de composição entre as classes Pessoa e Endereco foi mapeado para uma chave estrangeira (FK) na tabela Endereco que aponta para a chave primária (cdpessoa) da tabela Pessoa; essa chave estrangeira (cdpessoa) constitui a chave primária da tabela Endereco.
- O relacionamento de agregação entre as classes Prato e PessoaJuridica (fornecedor) foi mapeado para uma tabela associativa cuja chave primária é uma combinação das chaves primárias das tabelas Prato e PessoaJuridica (fornecedor). Se não estivéssemos diante de um relacionamento muitos-para-muitos, a solução seria a mesma usada para mapear um relacionamento de dependência.
- O mapeamento do relacionamento de herança entre as classes Pessoa e PessoaFisica foi feito para uma chave estrangeira (FK) na tabela PessoaFisica que aponta para a chave primária (cdpessoa) da tabela Pessoa; essa chave estrangeira constitui a chave primária da tabela PessoaFisica.
Há duas outras formas de mapear o relacionamento de herança: usando uma única tabela ou tabelas independentes. Essas soluções, entretanto, são questionáveis do ponto de vista da normalização, sendo preferível a que usei no exemplo na qual se tem uma tabela para cada classe.
É isso, pessoal. Para criar as tabelas do JPratosProntos no banco de dados H2, use ESTE SCRIPT SQL.
Para saber como implementar a persistência de relacionamentos muitos-para-muitos em Java, leia ESTE ARTIGO.
Referências consultadas:
FOWLER, Martin. Padrões de arquitetura de aplicações corporativas. Porto Alegre: Bookman, 2006.
LARMAN, Craig. Utilizando UML e padrões. Porto Alegre: Bookman, 2004.
HORSTMANN, Cay. Padrões e projeto orientados a objetos. Porto Alegre: Bookman, 2007.
MACHADO, Felipe Nery Rodrigues. Banco de dados: projeto e implementação. São Paulo: Érica, 2004.





Parabéns pelo post. Fiquei com dúvidas, se puder me responder:
- Por que a chave-primária de pessoafisica é composta? Não poderia ser somente codpessoa, já que ela será única?
- Sendo a PK de pessoafísica composta por codpessoafisica e codpessoa, esses 2 campos não teriam que ser FK de funcionario (e não somente codpessoafisica)?
Obrigado.
Marcos,
Todo mapeamento é feito com base em chaves estrangeiras, único recurso de que dispomos nos bancos de dados relacionais para relacionar tabelas, fonte dos dados.
Uma pessoa física herda de uma pessoa, logo temos como chave estrangeira em pessoafisica a chave primária de pessoa para que possamos saber de que pessoa pessoafisica herda. O mesmo se dá com funcionario. Veja que funcionario herda diretamente de pessoafisica, logo precisamos da chave primaria de pessoafisica como chave estrangeira de funcionario para sabermos de quem ele herda.
Abraços,
Antonio Passos
Parabens pelo seu post . Estou mapeando meu tcc e ele sanou algumas duvidas minhas, porem ainda possuo um problema eu tenho uma classe endereco onde a mesma faz associacao com uma classe pedido e uma classe pessoa, pois o pedido necessita do endereco de entrega e pessoa o endereco onde mora. Como devo mapear isso no banco de dados? Eu criei uma fk para endereco dentro de pessoa e outra fk de endereco dentro de pedido e fico controlando o delete cascade pela aplicacao. Nao gostei muito desse modo e estava pensando em criar duas fks dentro de endereco apontando para pedido e outra para o cliente, mas as mesmas nao podem ser pk pois nunca as duas sao preenchidas juntas. O que voce sugere?
Obrigado pela atenção
Thiano,
Não vejo necessidade de vc associar um endereço aos pedidos.
Uma pessoa possui endereço (ou endereços, no plural). Logo, quando vc instancia uma pessoa, tem acesso aos seus endereços (residência, trabalho, outro).
O que vc pode fazer é incluir um atributo a mais no pedido que corresponda ao endereço de entrega do pedido (1 – Residência; 2- Trabalho; 3 – Outro).
Antonio Passos
Olá,
Sua explicação de como funciona o mapeamento de orientação a objetos para bd relacionais foi bem legal, mas eu cheguei até aqui com uma dúvida e ainda continuo com ela…
No seu modelo de dados você não usa o modelo entidade relacionamento, mas se eu tiver duas classes, por exemplo Conta e Cliente, usando o modelo entidade relacional, existiria então um relacionamento “Possui” entre elas, implicando que eu tenha um tabela representando esse relacionamento no modelo lógico e consequentemento no meu bd (eu sei que essa tabela nesse caso é opcional). Então eu teria que criar uma classe Possui no meu programa? (assumindo a obrigatoriedade desta tabela Possui). Se Sim que atributos eu colocaria nessa classe?
Não sei se vc vai poder me ajudar, mas espero que sim…
Obrigado!