O mapeamento objeto-relacional (ORM ou MOR) é uma técnica de muito utilizada para converter dados entre bancos relacionais e linguagens orientadas a objeto, como é o caso do PHP, C++, Java, Python, Ruby, entre outras.
Apesar das linguagens de programação modernas possuírem recursos da POO (Programação Orientada a Objetos), a maioria dos SGBD (Sistemas de Gerenciamento de Bases de Dados) é baseada no modelo relacional, onde temos tabelas ao invés de objetos.
Guardar instâncias de objetos em registros de tabelas é o objetivo das técnicas de MOR (Mapeamento Objeto Relacional).
A prática de mapear objetos relacionais tem grande importância no desenvolvimento de projetos. Hoje, eu manterei o foco em apresentar os pontos mais importantes da prática. Vamos lá!
Como funciona o mapeamento objeto-relacional?
O MOR (Mapeamento Objeto Relacional) nada mais é que o ato de conversão de objetos em memória para dados relacionais, e vice-versa.
Em geral, pressupõe-se que o modelo de dados já existe, e que temos que adaptar nosso sistema orientado a objetos para trabalhar com este esquema pré-existente. O modelo relacional é uma categoria que se destaca entre os SGBD.
Desde sua concepção, o SGBD tem provado ser um mecanismo eficiente e confiável de armazenamento de dados, que possibilita a manipulação, a manutenção da integridade e a segurança dos dados.
Os SGBDRs representam o mecanismo de persistência de maior aceitação e maturidade.
O propósito do MOR é, basicamente, prover uma camada de persistência transparente entre aplicação orientada a objeto e o mecanismo de persistência relacional.
O mecanismo de MOR atua na tradução transparente entre os modelos.
>>Leitura Recomendada:
Leia nosso manual prático de banco de dados NoSQL
Persistência em SGBDR
Por meio de MOR, é possível persistir os objetos em um SGBDR, obtendo-se todas as vantagens trazidas por ele, e evitando-se os problemas que aparecem ao realizar-se a persistência em OO, utilizando um modelo relacional (impedância de modelos).
A persistência de objetos por meio da técnica de MOR permite que se contorne a impedância existente entre as metodologias OO e Relacional, aproveitando assim os benefícios de ambas metodologias.
Persistência transparente refere-se à habilidade de se manipular os dados armazenados em um SGBDR diretamente pela linguagem orientada a objeto, e é o objetivo do MOR.
Isso retoma aos seguintes aspectos desejáveis em um sistema de persistência de objetos:
Persistência Ortogonal
Válida para todos os objetos do sistema, independente de seu tipo.
Persistência Transitiva
Se um objeto é persistente, todos os objetos referenciados por esse objeto devem ser promovidos a objetos persistentes.
A camada de persistência
A camada de persistência deve intermediar a camada de dados e a camada de aplicação.
Esse tipo de solução tem como foco aplicações que necessitam acessar dados legados, bases heterogêneas, ou gerenciar objetos de negócio distribuídos e persistentes.
Deve apresentar recursos de consulta de dados, suporte a transações, concorrência (locking otimista ou pessimista) e, enfim, possibilitar a persistência transparente, encapsulando o acesso ao banco de dados relacional.
Objetos, além de dados, possuem comportamento. Objetos podem ser multivalorados, englobando objetos complexos ou mesmo outros objetos, e terem atributos provenientes de relacionamentos (herança) com outros objetos.
Estas, entre outras características, trazem uma camada de complexidade a mais no âmbito da persistência.
Os SGBDR são considerados sistemas críticos na maioria das organizações, enquanto os SGBDOO são adotados no desenvolvimento das aplicações de negócio.
Isso reforça a necessidade do uso de metodologias que permitam uma integração efetiva entre as interfaces, que tendem a ser orientadas a objetos, e os dados, armazenados no modelo relacional.
O modelo relacional envolve a existência de tabelas unidimensionais de armazenamento de dados, onde cada linha representa um determinado registro no banco de dados.
É uma abordagem simples e eficiente de persistência, entretanto, retorna-se ao problema inicial da impedância entre o modelo relacional e a POO.
Objetos incluem estruturas de dados como listas e mapas, e utilizam herança e ligações diretas entre os objetos para se relacionarem entre si. Além disso, os objetos são criados e modificados em memória, sendo necessário coordenar o que ocorre na memória com o que ocorre em disco.
De uma forma geral, na persistência de objetos em SGBD, a identidade dos objetos, seus relacionamentos (herança, agregação e associação) e seu estado devem ser preservados nas tabelas relacionais.
Qual problema a camada de persistência resolve?
A criação de uma camada de persistência de objetos permite diminuir o acoplamento entre o banco de dados e a aplicação.
Desta forma, uma mudança em um modelo pode ser traduzida no outro, sem que haja a necessidade de se reestruturar toda a aplicação.
Por meio da camada de MOR, pequenas mudanças no esquema relacional deixam de afetar o código orientado a objeto como um todo e, assim, evita-se a necessidade do desenvolvedor da aplicação de atuar também como um administrador de dados, a partir do momento que o conhecimento do esquema do banco deixa de ser fundamental.
Técnicas de mapeamento objeto-relacional
A principal tarefa do MOR envolve a identificação das construções da orientação a objetos que se deseja extrair do esquema relacional, entre elas a identificação das classes e dos relacionamentos.
As principais técnicas de mapeamento de objetos em SGBDR podem ser descritas como:
1.Mapeamento Classe – Tabela
Mapeamento de uma classe em uma ou mais tabelas, ou de uma tabela para uma ou mais classes, e mapeamento de herança.
2. Mapeamento Atributo – Coluna
Mapeamento de tipos em atributos.
2. Mapeamento Relacionamento – Chave estrangeira
Mapeamento dos relacionamentos OO em relacionamentos entre tabelas.
Categorias da estratégia de mapeamento classe-tabela
Mapeamento de Subset
Onde os atributos da classe persistente representam algumas ou todas colunas de uma tabela.
Esta estratégia convém para casos onde todos os atributos de uma classe persistente são mapeados a uma mesma tabela, e onde não há preocupação de incluir as colunas que não fazem parte do modelo de negócios. Pode referir-se também à herança de tabelas simples.
Mapeamento de Superset
Onde os atributos da classe persistente são derivados de colunas de múltiplas tabelas.
Este tipo de mapeamento é usado para criar “classes de visão”, que ocultam o modelo físico de dados, ou para mapear uma árvore de herança de classes utilizando o mapeamento vertical.
Atributos de uma classe
Atributos Primitivos
Atributo de uma classe que é mapeado a uma coluna de uma tabela. Valor de um tipo de dados específico (int, float, double, dentre outros).
Atributos de Referência
Atributos que representam relacionamentos com outras classes. Atributos cujo tipo é uma referência a outro objeto ou conjunto de objetos (composição).
As relações entre objetos são implementadas explicitamente através de atributos de referência, enquanto as relações entre tabelas são realizadas através de associações de chaves estrangeiras.
O mapeamento de associações preocupa-se, basicamente, com algumas categorias de relacionamentos entre objetos.
Uma baseia-se na multiplicidade, outra baseia-se em dois tipos de direcionalidade (Relacionamentos Unidirecionais e Relacionamentos Bidirecionais).
Outra forma de relacionamento entre objetos são os Relacionamentos Recursivos (por exemplo, um time pode ser integrante de outros times).
Um aspecto essencial da POO é a herança. A herança permite que dados e comportamentos de uma superclasse sejam reaproveitados por subclasses. Bancos de dados relacionais não possuem o conceito de herança.
Entidades não podem herdar atributos de outras entidades.
Principais técnicas de representação de hierarquias em mapeamento relacional
Mapeamento Distribuído de Herança (Horizontal e Vertical)
Forma mais difícil de ser implementada quando coleções heterogêneas de objetos precisam ser recuperadas. Cada subclasse é mapeada em uma tabela separada, e todos os atributos herdados são replicados na tabela.
Mapeamento de Filtro de Herança
Forma mais rápida de mapeamento. Custo de manutenção e espaço. As classes são representadas em uma única tabela. Cada registro da tabela utiliza atributos pertinentes à sua subclasse, enquanto os outros atributos são mantidos nulos.
O que é preciso atentar?
No processo de mapeamento também é importante levar em consideração quais informações adicionais deverão ser mantidas pelo objeto, por exemplo, informação de chave primária, de contadores e números de versionamento.
Outra informação relevante refere-se à existência do objeto no banco de dados, o que resultaria na decisão entre um comando UPDATE da linguagem SQL, ou de um comando INSERT.
Uma técnica para isto seria implementar uma variável booleana a cada classe persistente. Essas informações não precisam ser implementadas nos objetos de negócio, mas devem ser tratadas de alguma forma pela aplicação de MOR.
Como foi visto, há mais de uma forma de efetuar-se o mapeamento entre o modelo de objetos e o modelo de dados relacional.
A estratégia de encapsulamento do acesso ao banco de dados determinará como será implementado o mapeamento.
>> Quiz recomendado:
Quiz do SQL: o quanto você manja?
Padrões de MOR
Padrões de projeto são modelos conceituais que podem ser aplicados em determinadas áreas de uma aplicação de acordo com a necessidade.
Em geral, as ferramentas de MOR são desenvolvidas para trabalhar com um “Modelo de Domínios” (Domain Model).
Sua base é a criação de um modelo de objetos que incorpora ambos os dados e o comportamento, criando uma rede de objetos interligados.
É similar a um modelo de banco de dados, mas envolve dados e processos, atributos multivalorados e herança. Confira os 4 principais modelos padrão de arquitetura:
Row Data Gateway
É um objeto que age como um gateway para um único registro no banco de dados, ou seja, um objeto que reflete um registro de uma tabela.
Table Data Gateway
Age sobre uma tabela, mantendo todo o código SQL de acesso, encapsulando a lógica de acesso do banco de dados.
Active Record
Combina o gateway e o objeto de domínio em uma única classe, combinando a lógica de negócio e o acesso ao banco de dados.
Data Mapper
O mais flexível e o mais complexo. Age como um mediador entre os objetos em memória e o banco de dados, podendo ignorar completamente o layout de banco de dados.
Sua responsabilidade é transferir dados entre ambos e geralmente é utilizado com um “Modelo de Domínios”. Há também outras duas questões envolvidas no processo de mapeamento:
Diferença de representação
Os objetos são referenciados em tempo real e em memória, enquanto os dados relacionais são referenciados por chaves que estão alocadas em outras tabelas.
Atributos multivalorados
Os objetos lidam com múltiplas referências em único campo, através de coleções, enquanto não há campos multivalorados no modelo relacional.
Uma forma de lidar com o primeiro problema é através da manutenção da identidade relacional de cada objeto com a adição de um campo identificador (armazenamento da chave primária nos atributos do objeto).
Para o segundo caso, geralmente utiliza-se uma técnica chamada de lazy loading, onde o objeto não contém todos os dados: os dados são atribuídos ao objeto apenas quando necessário.
Estruturas de herança de um modelo de objetos para um modelo relacional
Herança de tabela simples
Onde uma tabela representa todas as classes da hierarquia.
Herança horizontal
Onde cada classe não-abstrata é associada à sua respectiva tabela, incluindo os atributos da classe herdada.
Herança vertical
Onde cada classe da hierarquia, inclusive classes abstratas, é associada a uma tabela separada no banco de dados.
Sobre mapeamento objeto-relacional, qual a conclusão?
A utilização de técnicas de MOR possibilita às empresas que tem como base SGBDR, direcionarem seus investimentos em inovação e tecnologia, com a utilização de soluções OO, e ao mesmo tempo, manterem a confiabilidade, segurança, e tradição dos bancos de dados relacionais.
Por meio do MOR diminui-se o acoplamento entre o modelo de dados relacional e a aplicação OO, permitindo a portabilidade e a escalabilidade futura das aplicações.
Desenvolvendo projetos desta maneira você estará contribuindo para a reutilização do seu código em diferentes áreas do seu sistema e até mesmo de projetos futuros, sem falar da legibilidade e do aspecto profissional agregado ao seu código.
Até a próxima!