Breve Introdução sobre Hibernate com Anotaçõespor: Raphaela Galhardo (raphaela@jeebrasil.com.br) Este artigo trata de uma introdução à utilização do framework Hibernate com anotações. Será apresentada uma breve introdução sobre anotações, bem como um exemplo simples de mapeamento objeto relacional com anotações Hibernate. 1. IntroduçãoRecentemente, o mapeamento objeto relacional utilizando Hibernate passou a ser feito também a partir de anotações, de forma que se tornou mais simples, possibilitando uma maior produtividade no desenvolvimento de aplicações. As anotações podem ser definidas como metadados que aparecem no código fonte e são ignorados pelo compilador. Qualquer símbolo em um código Java que comece com uma @ (arroba) é uma anotação. Este recurso foi introduzido na linguagem Java a partir da versão Java SE 5.0. Em outras palavras, as anotações marcam partes de objetos de forma que tenham algum significado especial. A Listagem 1 e a Listagem 2 apresentam exemplo de um tipo de anotação denominado de TesteAnotacao e do seu uso em um método qualquer (metodoTeste), respectivamente. O exemplo é meramente ilustrativo, de forma que o tipo de anotação definido não agrega nenhum significado especial ao código fonte. public @interface TesteAnotacao{ ... } Listagem 1 – Exemplo ilustrativo para a criação de um tipo de anotação @TesteAnotacao public void metodoTeste{ ... } Listagem 2 – Exemplo ilustrativo para o uso de um tipo de anotação Inicialmente, o mapeamento objeto relacional com Hibernate era feito a partir de um conjunto de configurações em arquivos XMLs. Com o surgimento das anotações no Java SE 5.0, o framework Hibernate anexou este recurso, permitindo que as classes Java fossem mapeadas a partir de anotações, simplificando o seu uso. A próxima seção apresentará um exemplo simples do uso da persistência de uma classe com Hibernate Annotations. 2. Exemplo Simples com Anotações HibernateInicialmente, para que o Hibernate soubesse como carregar e armazenar objetos de classes persistentes, eram utilizados apenas arquivos de mapeamento XML. Dessa forma, era possível informar que tabela do banco de dados se refere uma dada classe persistente e quais colunas na tabela são referentes a quais atributos da classe. Com o surgimento das anotações no Java 5.0, tornou-se possível substituir os arquivos XML para o mapeamento objeto relacional. Através do uso de um conjunto de anotações no código fonte das classes mapeadas. Neste primeiro exemplo, será apresentado como realizar o mapeamento objeto relacional da classe Aluno (Classe ilustrada na Figura 1) utilizando anotações. Dessa forma, informando ao Hibernate que tabela no banco de dados a representa e quais atributos correspondem as quais colunas desta tabela.
Figura 1 - Classe Aluno A classe Java que representa a entidade Aluno está ilustrada na Listagem 3. package br.com.jeebrasil.dominio; public class Aluno { //Atributos da classe private int id; private int matricula; private String nome; private long cpf; //Construtor padrão public void Aluno(){} //Métodos getters e setters public long getCpf() { return cpf; } public void setCpf(long cpf) { this.cpf = cpf; } 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 3 - Classe de Domínio: Aluno Para os exemplos ilustrados neste material, a base de dados foi feita utilizando o PostgreSQL 8.2, que pode ser baixado no site www.posgresql.org. A classe Aluno foi mapeada para a tabela aluno presente no esquema anotacoes do banco criado denominado jeebrasil. O script para a criação da tabela aluno pode ser visto na Listagem 4. CREATE TABLE anotacoes.aluno ( id_aluno integer NOT NULL, -- Identificador da tabela matricula integer NOT NULL, -- Matrícula do aluno nome character(40) NOT NULL, -- Nome do aluno cpf bigint NOT NULL, -- CPF do aluno CONSTRAINT pk_aluno PRIMARY KEY (id_aluno), CONSTRAINT un_cpf_aluno UNIQUE (cpf), CONSTRAINT un_matricula_aluno UNIQUE (matricula) ) WITHOUT OIDS; ALTER TABLE anotacoes.aluno OWNER TO postgres; COMMENT ON COLUMN anotacoes.aluno.id IS 'Identificador da tabela'; COMMENT ON COLUMN anotacoes.aluno.matricula IS 'Matrícula do aluno'; COMMENT ON COLUMN anotacoes.aluno.nome IS 'Nome do aluno'; COMMENT ON COLUMN anotacoes.aluno.cpf IS 'CPF do aluno'; Listagem 4 – Script para a criação da tabela aluno Todas as classes persistentes mapeadas com anotações Hibernate são declaradas usando a anotação @Entity, aplicada em nível de classes, como mostrado na Listagem 5. Observa-se que com o uso de anotações, não há mais a necessidade de se utilizar arquivos de mapeamento XML adicionais. Quando o nome da classe é diferente do nome da tabela para a qual é mapeada é necessário informar na anotação @Table qual o nome da tabela, usando o atributo name. No caso do mapeamento da classe Aluno, não havia a necessidade de se informar o nome da tabela, pois ela e a classe possuem o mesmo nome. Como a tabela pertence a um esquema do banco de dados (anotacoes), no mapeamento da classe, também é necessário informar em que esquema a tabela mapeada se encontra, utilizando o atributo schema da anotação @Table. No caso, a linha do código fonte @Table(name="aluno", schema="anotacoes") está informando o nome e o esquema da tabela para a qual está mapeada a classe aluno. A chave primária da tabela é mapeada na classe através da anotação @Id. O valor atribuído à chave primária pode ser dado tanto pela aplicação quanto por um mecanismo do Hibernate que o gere automaticamente. A anotação @GeneratedValue permite a definição automática para o valor do identificador, utilizando um dos mecanismos de geração apresentados anteriormente. Neste caso, utilizou-se a estratégia a partir de uma seqüência, como feito na linha de código @GeneratedValue(strategy = GenerationType.SEQUENCE). Dessa forma, na hora de persistir uma linha na tabela aluno, o Hibernate vai pegar como valor para a chave primária o próximo valor disponível por uma seqüência padrão chamada hibernate_sequence. Deve-se salientar que o programador deverá criar uma seqüência com este nome na base de dados. Ainda em relação ao identificador, como o nome da coluna mapeada é diferente do nome do atributo, é necessário utilizar a anotação @Column informando o nome da coluna, através do atributo name. Neste exemplo, o nome da coluna mapeada para o identificador é id_aluno, mapeada da seguinte forma: @Column(name="id_aluno"). Observa-se que nos demais atributos da classe não há nenhuma anotação de mapeamento. Isso pode ser feito quando o nome do atributo é igual ao nome da coluna da tabela mapeada, de forma que não há a necessidade de mapeamento explícito. Por fim, para se utilizar as anotações para mapeamento das classes, é preciso importá-las de algum lugar, neste caso do pacote javax.persistence, como mostrado no início do código fonte da Listagem 10. package br.com.jeebrasil.hibernate.anotacoes.dominio; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; //Anotação que informa que a classe mapeada é persistente @Entity //Informando nome e esquema da tabela mapeada @Table(name="aluno", schema="anotacoes") public class Aluno { //Definição da chave primária @Id //Definição do mecanismo de definição da chave primária @GeneratedValue(strategy = GenerationType.SEQUENCE) //Informa o nome da coluna mapeada para o atributo @Column(name="id_aluno") private int id; private int matricula; private String nome; private long cpf; public void Aluno(){} //Métodos getters e setters //... } Listagem 10 – Mapeamento da classe Aluno com anotações Depois de criar todas as classes persistentes com seus respectivos mapeamentos com anotacoes, deve-se realizar algumas configurações do Hibernate, mostradas na seção seguinte. 2.1 Configurando a Base de DadosPara tudo funcionar corretamente, é necessário realizar algumas configurações da base de dados. Essas configurações podem ser feitas a partir de um arquivo XML, em geral, denominado hibernate.cfg.xml. A partir deste arquivo, é possível realizar algumas configurações relacionadas à base de dados, bem como informar as classes mapeadas com anotações que poderão ser persistidas a partir dos mecanismos do Hibernate. A Listagem 6 apresenta um exemplo para o arquivo de mapeamento hibernate.cfg.xml, onde alguns parâmetros são configurados, como:
<?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"> Listagem 6 - Arquivo de Configuração hibernate.cfg.xml Resumindo as descrições das propriedades configuradas no arquivo hibernate.cfg.xml:
Já no final do arquivo hibernate.cfg.xml é onde devem ser informados os arquivos das classes mapeadas que o Hibernate deve processar. Se alguma classe não for definida neste local, a mesma não poderá ser persistida utilizando os mecanismos do Hibernate. Para este exemplo, apenas uma classe foi
mapeada. Se existissem outras classes persistentes, as mesmas
deveriam ter linhas semelhantes a 3. Exemplo de PersistênciaO 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 Listagem 7 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 AnnotationConfiguration() 5. .configure( 6. "/br/com/jeebrasil/hibernate/anotacoes/conf/hibernate.cfg.xml") 7. .buildSessionFactory(); 8. 9. Session session = sf.openSession(); //Abre sessão 10. Transaction tx = session.beginTransaction(); //Cria transação 11. 12. //Cria objeto Aluno 13. Aluno aluno = new Aluno(); 14. aluno.setNome("Raphaela Galhardo Fernandes"); 15. aluno.setMatricula(200027803); 16. aluno.setCpf(1234567898); 17. session.save(aluno); //Realiza persistência 18. tx.commit(); //Fecha transação 19. session.close(); //Fecha sessão 20 21. }catch(HibernateException e1){ 22. e1.printStackTrace(); 23. }catch(SQLException e2){ 24. e2.printStackTrace(); 25. } Listagem 7 - Exemplo de Persistência da Classe Aluno O código presente nas linhas 4-7 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 As Listagem 8 e Listagem 9 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 8 - Exemplo de Busca e Atualização de um Objeto Aluno ... 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 9 - Exemplo de Remoção de Objeto Aluno 4. ConclusõesCom este artigo, procurou-se passar uma breve introdução sobre a utilização do framework Hibernate utilizando anotações. As anotações surgiram melhorando o desenvolvimento das aplicações com Hibernate, considerando uma melhora de produtividade no que dizia respeito a uso de arquivos XML’s para a realização do mapeamento objeto relacional. Lembrando que o uso de anotações apenas provocou o surgimento de uma nova sintaxe para o mapeamento objeto relacional com Hibernate. Não houve adição de novos recursos ao framework, apenas unificou-se as configurações nas classes Java.
|