É notório o crescimento da área de desenvolvimento de software nos últimos 20(vinte) anos. Para acompanhar o crescimento, novas metodologias foram surgindo com o intuito de facilitar o desenvolvimento. Por muito tempo um dos maiores problemas encontrados na codificação estava na necessidade de efetuar transações com banco de dados (a grande maioria das aplicações necessitam interagir com algum banco de dados). Um outro problema comum é a dificuldade de manter código muito acoplado, contendo códigos referentes ao domínio da aplicação misturados com códigos SQL. Na tentativa de resolver esses problemas surgiu o Hibernate, e logo após surgiu o JPA (Java Persistence API), permitindo trabalhar ORM (Modelo Objeto Relacional) de forma transparente, sem a necessidade direta de utilizar código SQL, por meio de anotações (annotations) e fazendo uso de recursos como o refflaction. Nas listagens abaixo serão mostrados exemplos e dicas para trabalhar com os frameworks de persistência.

Para representar o exemplo será desenvolvida uma pequena aplicação que persiste um objeto contendo uma lista de enumeradores utilizando anotações JPA para a persistência e relacionamentos.

Criando o Código


package br.com.nooclix.domain;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.SequenceGenerator;

import org.hibernate.annotations.CollectionOfElements;

@Entity(name = "tb_person")
public class Person {
	@Id
	@SequenceGenerator(initialValue = 1, allocationSize = 1, 
	sequenceName = "person_seq", name = "person_seq")
	@GeneratedValue(strategy = GenerationType.AUTO, 
	generator = "person_seq")
	@Column(nullable = false)
	private Integer code;
	private String firstName;
	private String lastName;

	@CollectionOfElements(targetElement = PersonType.class, 
	fetch = FetchType.EAGER)
	@JoinTable(name = "tb_persontype", joinColumns = 
	@JoinColumn(name = "persontypeid"))
	@Column(name = "persontype", nullable = false)
	@Enumerated(EnumType.STRING)
	private List<PersonType> listPersonType;

	//Getters() and Setters()
}
Listagem 1. Classe que contém a lista de Enum

A anotação @Entity indica que a classe Person ao ser persistida formará uma entidade com o nome tb_person. Logo mais abaixo observa-se a anotação @Id que define a chave primária da entidade tb_person. Mais abaixo a anotação @SequenceGenerator(...) contém a sequência que a chave primária deve seguir, no exemplo acima, está indicando que a chave do primeiro valor da entidade tb_person será 1, cujo o nome da sequência será person_seq, essa alias para a sequência será utilizada na anotação seguinte @GeneratedValue que contém a estratégia a ser seguida para gerar as chaves primárias da entidade. No exemplo acima foi utilizado a estratégia AUTO, ou seja, a chave iniciará com o valor 1 e seguirá a sequência crescente. Os demais atributos da classe Person (firstName, lastName) serão acrescentadas à entidade na forma de colunas.

A lista de Enum's


package br.com.nooclix.domain;

public enum PersonType {
	ADMIN, MANAGER, SECRETARY
}
Listagem 2. Criando o Enum PersonType

No exemplo de código acima foi determinado um enum com 3(três) enumeradores, os quais serão usados para definir o tipo de Person que será salvo. Para os exemplos desse artigo será salvo uma lista de Enumeradores, permitindo assim conter na aplicação mais de um Person_Type por pessoa.

Na Listagem 1 as linhas de código 30 a 35 definem como se dará a persistência da lista de Enums, dessa forma, uma nova tabela será gerada permitindo ter uma junção entre as duas classes definido pela anotação @JoinColumn.

Criando a Conexão com o Banco


package br.com.nooclix.persistence;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
//Criando a fábrica de Conexões
public class ConnectionDB {
	private static EntityManagerFactory emf = Persistence
			.createEntityManagerFactory("JPA");
	private static EntityManager em;
	
	public static EntityManager getConnection(){
		return emf.createEntityManager();
	}
}
Listagem 3. Fábrica de conexões

O código acima é um exemplo de fábrica de conexões, dessa forma não será preciso criar a conexão com o *persistence.xml toda vez que for preciso iniciar uma transação com o banco, bastando somente chamar o método getConnection() para receber a conexão com o XML.


<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="JPA">
      
    <class>br.com.nooclix.domain.Person</class>
    
    <properties>
      <property name="hibernate.dialect" 
      value="org.hibernate.dialect.PostgreSQLDialect"/>
      <property name="hibernate.connection.url" 
      value="jdbc:postgresql://localhost:5432/devdb"/>
      <property name="hibernate.connection.driver_class" 
      value="org.postgresql.Driver"/>
      <property name="hibernate.connection.password" 
      value="123456"/>
      <property name="hibernate.connection.username" 
      value="postgres"/>
      <property name="hibernate.hbm2ddl.auto" 
      value="update"/>
    </properties>
  </persistence-unit>
</persistence>
Listagem 4. Criando o Persistence.xml

O JPA trabalha com o arquivo Persistence.xml para efetuar a conexão com o banco de dados, no exemplo acima têm-se a definição das tags “ .. ” contendo o caminho das classes que serão persistidas como entidades no banco de dados. Mais abaixo estão definidas as propriedades de conexão que no caso do exemplo desse artigo será utilizado o banco de dados PostgreSQL, contendo a url, nome, usuário e senha do banco. Por meio da tag “” é possível acessar o arquivo persistence.xml na fábrica de conexões (Listagem 3). O arquivo persistence.xml deverá estar obrigatoriamente dentro da pasta META-INF dentro do SRC do projeto.

Estrutura do projeto
Figura 1. Estrutura do projeto

Criando a classe de Persistência


package br.com.nooclix.persistence;

import javax.persistence.EntityManager;
import br.com.nooclix.domain.Person;

public class PersonDB {

	private EntityManager em;

	public PersonDB() {
		em = ConnectionDB.getConnection();
	}

	public void save(Person person) {
		em.getTransaction().begin();
		em.persist(person);
		em.getTransaction().commit();
		em.close();
	}
}
Listagem 5. Classe de Persistência

No exemplo de código acima, a classe PersonDB recebe por meio do construtor a conexão como banco de dados, mais abaixo o método save( ) inicia a transação com o banco de dados e persiste o objeto person passado por parâmetro pela para o método. Ao final do commit() o entityMangager chama o método close(), ou seja, a conexão com o banco de dados precisa ser fechada, dessa forma basta apenas ter uma única instância da classe PersonDB para que possa salvar o objeto de Person.

Persistindo o Objeto


package br.com.nooclix.execution;

import java.util.ArrayList;
import java.util.List;
import br.com.nooclix.domain.Person;
import br.com.nooclix.domain.PersonType;
import br.com.nooclix.persistence.PersonDB;

public class Execution {

	private Person person;
	private List<PersonType> listPersonType;
	private PersonDB personDB;

	public Execution() {
		person = new Person();
		listPersonType = new ArrayList<PersonType>();
		personDB = new PersonDB();
	}
	
	public void createPerson(){
		person.setFirstName("Yrineu");
		person.setLastName("Rodrigues");
		
		listPersonType.add(PersonType.ADMIN);
		listPersonType.add(PersonType.MANAGER);
		
		person.setListPersonType(listPersonType);
		
		personDB.save(person);
		System.out.println("Salvo com sucesso!");
	}
	
	public static void main(String[] args) {
		Execution ex = new Execution();
		ex.createPerson();
	}
}
Listagem 6. Executando o código

No exemplo de código acima a o método createPerson() define os valores do objeto Person, assim como a lista de UserType adicionado ao objeto Person como uma instância de ArrayList. Ao final o código personDB.save(person); envia o objeto person para o método save() através do objeto personDB, que por sua vez possui a sequência de chamadas para efetuar a persistência do objeto.

Desta forma serão criadas duas tabelas distintas, porém interligadas.

Tabelas criadas
Figura 2. Tabelas criadas
Valores das tabelas
Figura 3. Valores das tabelas

Conclusão

Com o uso de frameworks ORM como o JPA/Hibernate é possível inserir, por meio de anotações, criação de tabelas e administrar os valores das mesmas sem a necessidade direta de envolver código SQL, tornando o código mais limpo e menos acoplado. Com o auxílio dos frameworks ORM é possível ainda trabalhar com linguagens Orientada a Objetos como o exemplo do Java, permitindo utilizar todos os seus recursos, como por exemplo o uso de Enumeradores.