104 MAPEAMENTO OBJETO-RELACIONAL EM JAVA E PHP Josiel Silva Moura1 Carlos David Rocha de Souza 1 RESUMO Atualmente, é comum o uso de bancos de dados relacionais no meio corporativo e da programação orientada a objetos nas aplicações de interface. Os desenvolvedores frequentemente deparam-se com estes dois paradigmas diferentes: o modelo relacional e o modelo de objetos. Este estudo tem como objetivo apresentar as principais técnicas de persistência de objetos, com relevância na técnica de Mapeamento Objeto-Relacional em Java. Compreender os conceitos da técnica ORM é o primeiro passo para usar efetivamente os frameworks disponíveis. Palavras-chave: Objeto-Relacional, Banco de Dados, Java, PHP. ABSTRACT Currently, it is common to use relational databases in the corporate environment and object-oriented programming interface for applications. Developers often are faced with these two different paradigms: the relational model and object model. This study aims to present the main techniques for object persistence, with relevance to the technique of ObjectRelational Mapping in Java. Understand the concepts of ORM technique is the first step to effectively use the available frameworks. Key-Words: Object-Relational, Database, Java, PHP. 1 INTRODUÇÃO A orientação a objeto provê diversos benefícios em relação a sua predecessora (a análise estruturada), tais como encapsulamento, polimorfismo, herança, etc. Essas características proporcionam soluções muito mais fáceis de representação através da orientação a objeto traduz os objetos do mundo real da forma como eles realmente são em oposição à representação de funcionalidades como era na análise estruturada. Se, por um lado, as aplicações são beneficiadas por uma abordagem orientada a objeto, a persistência dos dados nos bancos relacionais demanda uma atenção muito maior, pois a tradução entre esses dois mundos não é direta. Como existem diferenças conceituais entre o modelo relacional usados pelos bancos de dados e a orientação a objetos, acabou surgindo a técnica de mapeamento objeto-relacional (ORM). Essa técnica sugere como devemos persistir o estado de um objeto (atributos, relacionamentos e herança) em tabelas de banco de dados relacional. Diversas plataformas e linguagens promovem essa técnica através de frameworks. Na plataforma Java existe o consagrado framework Hibernate (Hibernate, 2011) e o padrão chamado JPA (Biswas, et al., 2006). Em PHP temos o LUMINE (Lumine, 2008). Já na plataforma .NET também podemos encontrar o NHibernate (um porte do Hibernate para .NET) e o Microsoft ObjectSpaces (Esposito, 2004), dentre outros. Compreender os conceitos da técnica ORM é o primeiro passo para usar efetivamente os frameworks disponíveis. Scott W. Ambler em (Ambler, 2009) e (Ambler, 2010), descreve minuciosamente essa técnica, além de discutir o gap conceitual entre o modelo relacional e a orientação a objetos. 2. MAPEAMENTO OBJETO-RELACIONAL Grande parte do desenvolvimento de aplicações modernas utiliza a tecnologia orientada a On-line http://revista.univar.edu.br/ ISSN 1984-431X objetos, mas mantém como principal meio de persistência os bancos de dados relacionais (NASSU, et al., 1999). Enquanto o paradigma da orientação a objetos é baseado em princípios provados pela engenharia de software, o paradigma relacional é baseado em princípios matemáticos, especificamente em teoremas da álgebra relacional. Por consequência das diferenças entre os dois modelos, há uma dificuldade do ponto de vista técnico para a implementação rápida e descomplicada de aplicações que envolvam programação em linguagem orientada a objetos e o armazenamento de informações em um SGBD relacional. Esse é um problema recorrente que recebeu o nome de "Impedance Mismatch" (Ambler, 2009) Há uma diferença de representação: os objetos são referenciados em memória, enquanto os dados são referenciados por chaves em tabelas, que existem fisicamente. Além disso, os objetos possuem campos multivalorados, ao contrário do modelo relacional, onde os dados devem ser atômicos. Veremos agora como fazer o mapeamento das relações da orientação a objetos, 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. 2.1 Chave de Identificação A forma que os bancos de dados relacionais encontram para dar unicidade aos seus registros é a criação de chaves primárias nas tabelas, nas quais criamos uma coluna cujo valor-chave é não-repetitivo e não-nulo (Date, 2004). Os objetos de um sistema não precisam de tal chave para se tornarem únicos. A unicidade dos objetos em memória é controlada por mecanismos da própria linguagem de programação, a qual geralmente oferece Interdisciplinar: Revista Eletrônica da Univar (2011) nº. 6 p. 104 - 108 105 meios de se referenciar um objeto, ou mesmo de clonar um objeto já existente, controlando sua identidade por meio de um OID (Object Identifier) (Dall'Oglio, 2009). De qualquer forma, dois objetos distintos são armazenados em regiões diferentes da memória e referenciados por suas variáveis. Como compatibilizar então o modelo conceitual e o modelo de dados da aplicação? A resposta consiste da criação da chave primária do registro também para os objetos de negócio da aplicação. A adoção dessa chave é de suma importância, uma vez que lemos as informações de um registro do banco de dados, instanciamos um objeto de negócio com tais informações, modificamos esse objeto e, em um dado momento, desejamos armazenar esse objeto novamente no banco de dados, substituindo suas informações originais. Isso é possível somente pela sua chave primária. 3. UMA SITUAÇÃO DE NEGÓCIO Para demonstrar esses conceitos, imagine que você possua uma estante repleta de livros e seja solicitado o desenvolvimento de um sistema para catalogar os livros e que o principal objetivo desse seja facilitar a consultar (busca) por um livro. A consulta deve ser feita pelo título do livro ou pelo autor. Em nosso sistema, a principal entidade deve ser o Livro, mas esse depende de algumas outras, tais como, Editora e Autor, esses não podem ser um atributo da entidade Livro, pois a Editora possui vários campos próprios (campo multivalorado) e um Livro poderá ter vários Autores (campo não-atômico). Veja abaixo o diagrama de EntidadeRelacionamento simplificada para nosso sistema de catálogo de livros. Figura 1:Diagrama criado no MySQL Workbench (2011) No mundo relacional um relacionamento um para um não é visto como uma boa prática de design, devendo ser utilizado apenas em casos especiais, conhecidos como particionamento horizontal ou vertical. Para esse tipo de associação, podemos adicionar uma chave estrangeira a uma das tabelas, mapeada para a chave estrangeira da outra tabela (Amaral, 2008). Dessa forma não abordaremos esse tipo de relacionamento aqui. 4. RELACIONAMENTO UM-PARA-MUITOS Observe o diagrama abaixo, ele representa o relacionamento entre as entidades Livro e Editora. Esse relacionamento é um relacionamento do tipo um-paraOn-line http://revista.univar.edu.br/ ISSN 1984-431X muitos, porque uma Editora pode ter muitos Livros enquanto um livro pode pertencer apenas a uma editora. Figura 2: Diagrama de Entidade-Relacionamento 1:1 A implementação em Java dos relacionamentos um-para-muitos é relativamente simples. Na classe de multiplicidade muitos (Livro), adicione um atributo do tipo da classe de multiplicidade um (Editora) e os correspondentes métodos get’s e set’s para esse atributo. Não nos preocuparemos com os Autores do Livro por enquanto. 4.1 Implementando as Classes de Entidades Devemos iniciar pela entidade que não possui dependência, ou seja, que ela exista por si própria, não dependendo de outras entidades (Deitel, 2005). Assim iniciaremos a criação a entidade Editora: 01 package entidade; 02 public class Editora { 03 private int codigo; 04 private String nome; 05 private String cidade; 06 private String site; 07 08 public Editora(){ 09 } 10 //geteres e seteres omitidos 42 } Listagem 1: Classe Editora.java Na classe Livro que possui dependência da classe Editora, devemos declarar o atributo editora do tipo Editora. Veja abaixo o código-fonte da entidade Livro: 01 package entidade; 02 public class Livro { 03 private int codigo; 04 private String titulo; 05 private String categoria; 06 private String edicao; 07 private String ano; 08 private Editora editora; 09 10 public Livro() { 11 } 12 13 //geteres e seteres omitidos 14 } Listagem 2: Classe Livro.java 4.2 RELACIONAMENTO MUITOS MUITOS-PARA- Interdisciplinar: Revista Eletrônica da Univar (2011) nº. 6 p. 104 - 108 106 Como exemplo desse tipo de relacionamento, considere a relação livro-autor: um livro pode ser escrito por vários autores; um autor, por sua vez, pode escrever vários livros. Na implementação dos relacionamentos muitos-para-muitos em bancos de dados relacionais, a solução tem sido usar uma tabela associativa que represente o relacionamento (Murta, et al., 2007). Para isso: Cria-se uma nova tabela no banco de dados para representar o relacionamento muitospara-muitos entre duas tabelas; Inclue-se como chave estrangeira dessa tabela as chaves primárias das tabelas que participam do relacionamento; Combina-se essas chaves estrangeiras para formar a chave primária da tabela associativa Veja diagrama o Digrama de Entidaderelacionamento para o contexto descrito: Na entidade Livro, iremos apenas acrescentar o atributo autores do tipo List da classe java.util.List, e seus respectivos get’s e set’s. 01 package entidade; 02 import java.util.List; 03 public class Livro { 04 05 private int codigo; 06 private String titulo; 07 private String categoria; 08 private String edicao; 09 private String ano; 10 private Editora editora; 11 private List<Autor> autores; 12 13 public Livro() { 14 } 15 //geteres e seteres omitidos 16 } Listagem 4: Classe Livro.java modificada As linhas que acrescentadas estão em destaque na listagem acima. Durante o projeto, colunas adicionais podem ser incluídas nas tabelas, visões que suportem requisitos de consulta e relatório podem ser criadas e índices podem ser elaborados para otimizar o desempenho. Não devem ocorrer grandes reestruturações da tabela ao longo do projeto do sistema, pois isso demonstra que a arquitetura não está estabilizada. Figura 3: Diagrama de Entidade-Relacionamento para livro e autor. 4.3 Implementando as Classes de Entidades Já na implementação dos relacionamentos muitos-para-muitos em programação orientada a objeto, utiliza-se campos multivalorados do tipo coleção, optou-se aqui por criar uma lista de autores na entidade Livro, assim iniciaremos a codificação pela entidade Autor. 01 package entidade; 02 03 public class Autor { 04 private int codigo; 05 private String nome; 06 private String email; 07 08 public Autor() { 09 } 10 //geteres e seteres omitidos 11 12 } Listagem 3: Classe Autor.java On-line http://revista.univar.edu.br/ ISSN 1984-431X 5 MAPEAMENTO DE OBJETO RELACIONAL EM PHP UTILIZANDO TABLE DATA GATEWAY A utilização de mapeamento de objetorelacioal era algo distante quanto ao uso da linguagem PHP já que a mesma não provia de métodos para persistência de dados em um banco de dados método o qual é bem desenvolvido nas plataformas JAVA e .Net. Em um contexto amplo e geral persistência significa continuar a existir, perseverar, durar longo tempo ou permanecer. Em uma linguagem de programação ou um plano de negócios persistência significa a possibilidade de esses objetos existirem em um meio externo à aplicação que os criou, de modo que esse meio deve permitir que o objeto perdure não deve ser um meio volátil, meio ao qual os bancos de dados modelo relacional utilizam tão bem com métodos específicos de cadê fabricante utilizando a linguagem SQL para armazenagem e manipulação de dados, mas existem conceitos na orientação a objetos para os quais o modelo relacional simplesmente não oferece suporte, levando ao paradigma de diferentes conceitos, o modelo relacional que utiliza a codificação estrutural e o orientado a objeto que trabalha com abstração e instanciação e encapsulamento de objetos. A implementação do código abaixo busca solucionar o problema do banco relação em relação à síntese de orientação a objeto em PHP. Para mapear o objeto Editora, foi utilizada a técnica de pattern Table Data Gateway (Fowler, 2010) que oferece uma Interdisciplinar: Revista Eletrônica da Univar (2011) nº. 6 p. 104 - 108 107 interface de comunicação com o banco de dados que permite operações de inserção, alteração, exclusão e busca de registro. Implementando uma classe responsável em persistir e retornar dados do banco de dados. Para isso existem métodos específicos que traduzem sua função em instruções SQL. 01 <?php 02 03 class EditoraGateway { 04 /* 05 * método insert 06 */ 07 function insert($codigo, $nome, $cidade, 08 $site) { 09 // cria instrução SQL de insert 10 $sql = "INSERT INTO editora (codigo, 11 nome, cidade, site)" . 12 " VALUES ('$codigo', '$nome', 13 '$cidade', '$site')"; 14 15 // instancia objeto PDO 16 $conn = new 17 PDO('mysql:host=localhost;port=3306;dbname=l 18 ivros', 'root', ''); 19 $conn20 >setAttribute(PDO::ATTR_ERRMODE, 21 PDO::ERRMODE_WARNING); 22 // executa instrução SQL 23 $conn->exec($sql); 24 unset($conn); 25 } 26 27 /* 28 * método update 29 */ 30 function update($codigo, $nome, $cidade, 31 $site) { 32 // cria instrução SQL de UPDATE 33 $sql = "UPDATE editora set nome = 34 '$nome', " . 35 " cidade = '$cidade', site = '$site' " . 36 " WHERE codigo = '$codigo'"; 37 38 // instancia objeto PDO 39 $conn = new 40 PDO('mysql:host=localhost;port=3306;dbname=l 41 ivros', 'root', ''); 42 $conn43 >setAttribute(PDO::ATTR_ERRMODE, 44 PDO::ERRMODE_WARNING); 45 // executa instrução SQL 46 $conn->exec($sql); 47 unset($conn); 48 } 49 50 /* 51 * método delete 52 */ 53 function delete($codigo) { 54 // cria instrução SQL de DELETE 55 $sql = "DELETE FROM editora where 56 codigo='$codigo'"; On-line http://revista.univar.edu.br/ ISSN 1984-431X 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 10 0 10 1 10 2 10 3 10 4 10 5 10 6 10 7 // instancia objeto PDO $conn = new PDO('mysql:host=localhost;port=3306;dbname=l ivros', 'root', ''); $conn>setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); // executa instrução SQL $conn->exec($sql); unset($conn); } /* * método getObject * busca um registro da tabela editora */ function getObject($codigo) { // cria instrução SQL de SELECT $sql = "SELECT * FROM editora where codigo='$codigo'"; // instancia objeto PDO $conn = new PDO('mysql:host=localhost;port=3306;dbname=l ivros', 'root', ''); $conn>setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); // executa consulta SQL $result = $conn->query($sql); $data = $result>fetch(PDO::FETCH_ASSOC); unset($conn); return $data; } /* * método getObjects * lista todos registros da tabela editora */ function getObjects() { // cria instrução SQL de SELECT $sql = "SELECT * FROM editora"; // instancia objeto PDO $conn = new PDO('mysql:host=localhost;port=3306;dbname=l ivros', 'root', ''); $conn>setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); // executa consulta SQL $result = $conn->query($sql); $data = $result>fetchAll(PDO::FETCH_ASSOC); unset($conn); return $data; } } // instancia objeto ProdutoGateway $gateway = new EditoraGateway; Interdisciplinar: Revista Eletrônica da Univar (2011) nº. 6 p. 104 - 108 108 // insere alguns registros na tabela $gateway->insert(null, 'Novatec', 'São Paulo', 'www.novatec.com.br'); $gateway->insert(null, 'Moderna', 'São Paulo', 'www.editoramoderna.com.br'); $gateway->insert(null, 'Univar', 'Barra do Garças', 'www.univar.edu.br'); // efetua algumas alterações $gateway->update(1, 'Novatec', 'São Paulo - SP', 'www.novatec.com.br'); $gateway->update(2, 'Moderna', 'São Paulo', 'www.moderna.com.br'); // exclui $gateway->delete(3); // exibe novamente os registros echo "Lista de Editoras<br>\n"; print_r($gateway->getObjects()); ?> Listagem 5: Arquivo EditoraGateway.php Ao trabalhar com Table Data Gateway é necessário criar uma classe para manipulação de cada tabela de banco de dados, e apenas uma instancia dessa classe irá manipular todos os registros da tabela. 6 CONSIDERAÇÕES FINAIS Este artigo apresentou uma abordagem para o armazenamento de objetos Java em bancos de dados relacionais. A principal contribuição deste trabalho é prover uma solução transparente e acessível para o problema de mapeamento objeto-relacional. Apesar da relutância de alguns em adotar esquemas de persistência, fica evidente que sua utilização traz um ganho considerável de tempo na implementação de um sistema e eleva a qualidade do produto final, à medida que diminui a possibilidade de erros de codificação. O mapeamento objeto relacional pode ser feito tanto manualmente quanto automaticamente. O processo de mapeamento objeto relacional manual, que foi abordado neste artigo, é trabalhoso, pois torna-se necessário definir, para cada classe do sistema, como esta se relaciona e como será armazenada. Já o processo automático, suportado por uma ferramenta de mapeamento torna esse processo mais simples, mas nem sempre o torna transparente. Assim este trabalho cumpri o objetivo de mostrar a transparência desse processo, para em um trabalho futuro mostrar como é feito em um processo automatizado utilizando um framework disponível. 7 REFERENACIA BIBLIOGRÁFICAS AMARAL, Fernando. Dicas de Mapeamento Objeto/Relacional. 2008. Disponivel em <http://www.fernandoamaral.com.br/Default.aspx?Arti go=55>. Acessado em 21 de abril de 2011. em <http://www.agiledata.org/essays/mappingObjects.html >. Acessado em 20 de abril de 2011. _________ The Object-Relational Impedance Mismatch. 2009. Disponivel em <http://www.agiledata.org/essays/impedanceMismatch. html>. Acessado em 16 de abril de 2011. BISWAS, Rahul and Ort. The Java Persistence API - A Simpler Programming Model for Entity Persistence. 2006. Disponivel em <http://www.oracle.com/technetwork/articles/javaee/jp a-137156.html>. Acessado em 30 de maio de 2011. DALL'OGLIO, Pablo. PHP: programando com orientação a objetos. São Paulo : Novatec Editora, 2009. DATE, C.J. Introdução a Sistemas de Bancos de Dados. São Paulo : Campus, 2004. DEITEL, Paul J. Java: Como Programar. 6ª ed. Prentice-Hall, 2005. ESPOSITO, Dino. A First Look at ObjectSpaces in Visual Studio 2005. 2004. Disponivel em <http://msdn.microsoft.com/enus/library/ms971512.aspx>. Acessado em 23 de maio de 2011. FOWLER, Martin. Table Data Gateway. 2010. Disponivel em <http://martinfowler.com/eaaCatalog/tableDataGatewa y.html>. Acessado em 20 de abril de 2011. HIBERNATE. Hibernate - JBoss Community. 2011. Disponivel em <http://www.hibernate.org/>. Acessado em 10 de abril de 2011. LUMINE. Lumine - Database Mapping for PHP. 2008. Disponivel em <http://www.hufersil.com.br/lumine.>. Acessado em 23 de abril de 2011. MURTA, Leonardo Gresta Paulino, Veronese, Gustavo Olanda and Werner, Cláudia Maria Lima. MOR: Uma Ferramenta para o Mapeamento. Rio de Janeiro : UFRJ, 2007. MySQL. MySQL Workbench. 2011. Disponivel em <http://wb.mysql.com>. Acessado em 25 de maio de 2011. NASSU, E. A. and SETZER, W. W. Banco de Dados Orientado a Objeto. 1ª Edição. Editora Edgar Bkucher Ltda, 1999. AMBLER, Scott W. Mapping Objects to Relational Databases: O/R Mapping In Detail. 2010. Disponivel On-line http://revista.univar.edu.br/ ISSN 1984-431X Interdisciplinar: Revista Eletrônica da Univar (2011) nº. 6 p. 104 - 108