Primeiro Exemplo com Hibernatepor: Raphaela Galhardo (raphaela@jeebrasil.com.br) Este tutorial apresenta um primeiro exemplo utilizando o Hibernate . Será apresentado o arquivo de mapeamento de uma classe, juntamente com o arquivo de mapeamento para as configurações gerais do Hibernate . Por fim, serão mostradas manipulações de objetos persistentes, ou seja, como se criar, remover e atualizar objetos na base de dados utilizando o Hibernate . Primeiro Exemplo de Mapeamento com HibernateInicialmente, o Hibernate precisa saber como carregar e armazenar objetos de classes persistentes. Para isso, existe um arquivo de mapeamento XML que informa que tabela do banco de dados deve ser acessada para uma dada classe persistente e quais colunas na tabela são referentes a quais atributos da classe. Qualquer classe pode ser mapeada desde que seja um POJO. É recomendável que as tabelas possuam chaves primárias, de forma que se possa aproveitar ao máximo as funcionalidades do Hibernate. Para a maioria dos exemplos a serem ilustrados ao longo dos tutoriais, considere o digrama UML mostrado na Figura 1. Nele, é apresentado o domínio simplificado de uma universidade. Como se pode observar, uma universidade é formada por um identificador (id), um nome, possui um endereço e um conjunto de centros. Cada centro também possui um identificador (id), um nome, uma universidade a que pertence e é formado por um conjunto de departamentos. Cada departamento associa-se a um conjunto de cursos, possui uma coleção de professores e possui um professor como sendo seu chefe, além do seu identificador id e de seus demais atributos nome e sigla. Um curso possui um identificador, um código, um nome, uma sigla, um professor como seu coordenador, associa-se a um ou mais departamentos e possui um conjunto de alunos. Um professor possui um identificador, uma matrícula, um nome, um cpf e um departamento onde é lotado. Por fim, um aluno possui um identificador, uma matrícula, um nome, um cpf e um curso a que pertence.
Figura 1 - Diagrama UML: Domínio Universidade Neste primeiro exemplo, será apresentado o mapeamento da classe Aluno em um arquivo XML, que o Hibernate utiliza para saber que classe no banco de dados a representa. Os arquivos de mapeamentos XML entre classes e tabelas do banco de dados devem ser nomeados como *.hbm.xml (convenção definida pela comunidade de desenvolvedores do Hibernate). É nos arquivos com a extensão .hbm.xml que o Hibernate realiza o mapeamento objeto relacional. A classe que representa a entidade Aluno do diagrama da Figura 1 está ilustrada na Listagem 1. package br.com.jeebrasil.dominio; public class Aluno { private int id; private int matricula; private String nome; private long cpf; private Curso curso; public void Aluno(){} public long getCpf() { return cpf; } public void setCpf(long cpf) { this.cpf = cpf; } public Curso getCurso() { return curso; } public void setCurso(Curso curso) { this.curso = curso; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getMatricula() { return matricula; } public void setMatricula(int matricula) { this.matricula = matricula; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } } Listagem 1 - Classe de Domínio: Aluno Todos os arquivos XML que mapeiam as classes para as tabelas de banco de dados no Hibernate possuem a estrutura básica mostrada na Listagem 2. O arquivo XML começa normalmente com as definições da DTD (Definição do Tipo do Documento) e da tag raiz, o <hibernate-mapping>, depois vem a tag que nos interessa neste caso, <class>. Os elementos para o mapeamento objeto relacional encontram-se entre as tags hibernate-mapping. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> ... </hibernate-mapping> Listagem 2 - Estrutura Básica do Arquivo *.hbm.xml Para a classe Aluno considere seu arquivo de mapeamento como sendo o Aluno.hbm.xml. A partir deste momento, o cabeçalho do arquivo XML será ocultado e o conteúdo entre as tags hibernate-mapping será apresentado. O primeiro passo do mapeamento é informar que classe de domínio se refere a que tabela do banco de dados, através da tag <class>, como mostrado na Listagem 3. O único atributo obrigatório desta tag é o name, que contém o nome completo da classe. Se o nome da classe for diferente do nome da tabela a que se referencia, o nome da tabela é informado a partir do atributo table. <hibernate-mapping> <class name="br.com.jeebrasil.dominio.Aluno" table="ALUNO"> ... </class> </hibernate-mapping> Listagem 3 - Aluno.hbm.xml 1 Em seguida, mapeia-se a chave primária da tabela, como mostrado na Listagem 4. <hibernate-mapping> <class name="br.com.jeebrasil.dominio.Aluno" table="ALUNO"> <id name="id" column="ID_ALUNO" type="int"> <generator class="sequence"> <param name="sequence">aluno_seq</param> </generator> </id> </class> </hibernate-mapping> Listagem 4 - Aluno.hbm.xml 2 A tag id identifica a chave primária. O atributo name="id" informa o nome do atributo da classe Java que se refere à chave primária da tabela. O Hibernate utiliza os métodos getter e setter para acessar este atributo. O atributo column informa ao Hibernate que coluna na tabela é a chave primária, no caso ID_ALUNO. O atributo generator informa qual a estratégia para a geração da chave primária, para esse exemplo, a estratégia utilizada foi sequence. Dessa forma, o nome da seqüência também deve ser informado (aluno_seq) através da tag param. Agora as declarações das propriedades persistentes das classes serão incluídas no arquivo de mapeamento. Por padrão, os atributos das classes não são considerados como persistentes. Para se tornarem, é necessário incluí-los no arquivo de mapeamento. Na Listagem 5, são incluídos os mapeamentos das propriedades persistentes através da tag property. Essas tags indicam propriedades simples dos objetos, como por exemplo, String, os tipos primitivos e seus wrappers, objetos Date, Calendar, entre outros. <hibernate-mapping> <class name="br.com.jeebrasil.dominio.Aluno" table="ALUNO"> <id name="id" column="ID_ALUNO" type="int"> <generator class="sequence"> <param name="sequence">aluno_seq</param> </generator> </id> <property name="matricula" type="int" column="MATRICULA"/> <property name="nome"/> <property name="cpf" type="long" column="CPF" not-null="false"/> <many-to-one name="curso" class="br.com.jeebrasil.dominio.Curso" column="ID_CURSO"/> </class> </hibernate-mapping> Listagem 5 - Aluno.hbm.xml 3 Os nomes das propriedades da classe são definidos pelo atributo XML name, o tipo da propriedade pelo atributo type e a coluna da tabela a que se refere, por column. Observe que a propriedade nome não possui seu tipo e coluna a que se referenciam definidos. Se o atributo column não aparece no mapeamento da propriedade, o Hibernate considera que a coluna na tabela do banco de dados a que se referencia possui o mesmo nome que o definido pelo atributo name. Em relação ao atributo type não ser definido, o Hibernate também tenta, analisando o tipo da coluna na tabela, converter para o tipo adequado Java. O atributo not-null presente no mapeamento do atributo cpf serve para informar se a coluna pode ser ou não nula na tabela. Se for true, não pode ser nula. Se for false, pode assumir valor nulo. A última tag do arquivo <many-to-one> define o relacionamento n-para-1 que a classe Aluno tem com a classe Curso. Uma descrição mais detalhada desta tag será feita no próximo tutorial. Depois de criar todas as classes persistentes com seus respectivos mapeamentos *.hbm.xml, deve-se realizar algumas configurações do Hibernate. Configurando o HibernateExistem três maneiras distintas para se configurar o Hibernate:
Será apresentada a configuração a partir do arquivo hibernate.cfg.xml. Um exemplo deste arquivo de configuração pode ser visto na Listaegem 6. Vários parâmetros podem ser configurados. Basicamente, deve-se configurar:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <!-- a SessionFactory instance listed as /jndi/name --> <session-factory name="java:comp/env/hibernate/SessionFactory"> <!-- properties --> <property name="connection.driver_class"> org.postgresql.Driver </property> <property name="connection.url"> jdbc:postgresql://localhost:5432/banco </property> <property name="dialect"> org.hibernate.dialect.PostgreSQLDialect </property> <property name="show_sql">true</property> <property name="connection.username">postgres</property> <property name="connection.password">postgres</property> <property name="connection.pool_size">10</property> <!-- mapping files --> <mapping resource="br/com/jeebrasil/conf/Aluno.hbm.xml"/> <mapping resource=" br/com/jeebrasil/Centro.hbm.xml"/> <mapping resource=" br/com/jeebrasil/Curso.hbm.xml"/> <mapping resource=" br/com/jeebrasil/Departamento.hbm.xml"/> <mapping resource=" br/com/jeebrasil/Professor.hbm.xml"/> <mapping resource=" br/com/jeebrasil/Universidade.hbm.xml"/> </session-factory> </hibernate-configuration> Listagem 6 - hibernate.cfg.xml Resumindo as descrições das propriedades a serem configuradas:
O Hibernate trabalha com dialetos para um grande número de bancos de dados, tais como: DB2, MySQL, Oracle, Sybase, Progress, PostgreSQL, Microsoft SQL Server, Ingres, Informix entre outros. Possíveis valores para os dilates estão presentes na Listagem 7. DB2 - org.hibernate.dialect.DB2Dialect HypersonicSQL - org.hibernate.dialect.HSQLDialect Informix - org.hibernate.dialect.InformixDialect Ingres - org.hibernate.dialect.IngresDialect Interbase - org.hibernate.dialect.InterbaseDialect Pointbase - org.hibernate.dialect.PointbaseDialect PostgreSQL - org.hibernate.dialect.PostgreSQLDialect Mckoi SQL - org.hibernate.dialect.MckoiDialect Microsoft SQL Server - org.hibernate.dialect.SQLServerDialect MySQL - org.hibernate.dialect.MySQLDialect Oracle (any version) - org.hibernate.dialect.OracleDialect Oracle 9 - org.hibernate.dialect.Oracle9Dialect Progress - org.hibernate.dialect.ProgressDialect FrontBase - org.hibernate.dialect.FrontbaseDialect SAP DB - org.hibernate.dialect.SAPDBDialect Sybase - org.hibernate.dialect.SybaseDialect Sybase Anywhere - org.hibernate.dialect.SybaseAnywhereDialect Listagem 7 - Possíveis valores de dialetos O final do arquivo hibernate.cfg.xml é onde devem ser informados os arquivos de mapeamentos das classes que o Hibernate deve processar. Se algum arquivo de mapeamento não for definido neste local, a classe a que se refere não poderá ser persistida utilizando o Hibernate. Manipulando Objetos PersistentesO Hibernate utiliza objetos Session para persistir e recuperar objetos. Um objeto Session pode ser considerado como uma sessão de comunicação com o banco de dados através de uma conexão JDBC. O código fonte exibido na Tabela 8 mostra a criação e persistência de um objeto do tipo Aluno. ... 1. try{ 2. //SessionFactory deve ser criado uma única vez durante a execução 3 //da aplicação 4 SessionFactory sf = new Configuration() 5 .configure("/br/com/jeebrasil/conf/hibernate.cfg.xml") 6. .buildSessionFactory(); 7. 8. Session session = sf.openSession(); //Abre sessão 9. Transaction tx = session.beginTransaction(); //Cria transação 10. 11. //Cria objeto Aluno 12. Aluno aluno = new Aluno(); 13. aluno.setNome("Luis Eduardo Pereira Júnior"); 14. aluno.setMatricula(200027803); 15. aluno.setCpf(1234567898); 16. aluno.setCurso(curso); //Considera-se que o objeto “curso” já 17. //havia gravado na base de dados e 18. //recuperado para ser atribuído neste 19. // momento. 20. session.save(aluno); //Realiza persistência 21. tx.commit(); //Fecha transação 22. session.close(); //Fecha sessão 23. }catch(HibernateException e1){ 24. e1.printStackTrace(); 25. }catch(SQLException e2){ 26. e2.printStackTrace(); 27. } Listagem 8 - Exemplo de Persistência O código presente nas linhas 4-6 deve ser chamado uma única vez durante a execução da aplicação. O objeto SessionFactory armazena os mapeamentos e configurações do Hibernate. É um objeto pesado e lento de se criar. A Tabela 1 apresenta alguns dos métodos que podem ser invocados a partir do objeto Session.
Tabela 1 - Métodos invocados a partir do objeto Session Em relação ao método saveOrUpdate, uma questão que se pode formular é "Como o Hibernate sabe se o objeto em questão já existe ou não no banco de dados, ou seja, se ele deve ser criado ou atualizado?". A resposta é simples: o desenvolvedor deve informar isso a ele. Essa informação é incluída no arquivo de configuração *.hbm.xml da classe na tag que define a chave primária. No caso da classe Aluno, a tag da chave primária no arquivo Aluno.hbm.xml deve ter o atributo <unsaved-value> adicionado, como mostrado na Listagem 9. Neste caso com o atributo unsaved-value="0" significa que, no momento da chamada ao método saveOrUpdate(Objetc obj), se o atributo identificador do objeto estiver com valor 0 (zero) significa que ele deve ser criado na tabela do banco de dados. Dessa forma, se o seu valor for diferente de zero, o objeto deve ter sua linha na tabela atualizada (deve-se garantir que o valor do identificador do objeto se refere a um valor da chave primária da tabela). … <id name="id" column="ID_ALUNO" type="int" unsaved-value="0"> <generator class="sequence"> <param name="sequence">aluno_seq</param> </generator> </id> … Listagem 9 - Trecho de Aluno.hbm.xml As Listagens 10 e 11 apresentam exemplos dos métodos invocados a partir do objeto Session. ... Session session = sf.openSession(); Transaction tx = session.beginTransaction(); //Busca objeto aluno da base de dados com chave primária = 1 Aluno aluno = (Aluno) session.get(Aluno.class, 1); //Atualiza informação de matrícula. aluno.setMatricula(200027807); //Como o identificador do objeto aluno é diferente de 0, //a sua matrícula é atualizada já que foi alterada session.saveOrUpdate(aluno); tx.commit(); session.close(); ... Listagem 10 - Exemplo de Busca e Atualização de Objeto ... Session session = sf.openSession(); Transaction tx = session.beginTransaction(); Aluno aluno = new Aluno(); //Existe linha na tabela aluno com chave primária = 2 aluno.setId(2); //Deleta aluno com id = 2 da tabela. //Somente necessária informação do seu identificador session.delete (aluno); tx.comiit(); session.close(); ... Listagem 11 - Exemplo de Remoção de Objeto ConclusõesNeste tutorial foi apresentado um primeiro exemplo de mapeamento e como ele pode ser manipulado de forma persistente. Pode ser que a primeira impressão ao se utilizar o Hibernate seja que a criação dos mapeamentos é um pouco difícil e trabalhosa, mas à medida que novos exemplos vão sendo feitos e que se adquire a prática, verifica-se que utilizar o Hibernate como framework de mapeamento objeto-relacional trará benefícios, principalmente no quesito de produtividade. O próximo tutorial trará como mapear os relacionamentos entre as entidades utilizando o Hibernate. Referências
|