EntityManager

O EntityManager é um serviço responsável por gerenciar as entidades. Por meio dele é possível gerenciar o ciclo de vida das entidades, a operação de sincronização com a base de dados (inserir, atualizar ou remover), a consulta de entidades, entre outras operações.

Quando uma entidade está associada a um EntityManager, esta entidade está no contexto em que pode ser persistida, em que todas as operações realizadas no objeto da entidade é refletido no banco de dados. Todas as identidades das entidades são únicas, portanto para cada registro no banco de dados haverá apenas uma referência no contexto do EntityManager.

O EntityManager pode ser gerenciado de duas formas:

  • Gerenciado pelo Container;
  • Gerenciado pela Aplicação.

Unidade de Persistência

A unidade de persistência é utilizada para configurar as informações referentes ao provedor do JPA (implementação da especificação JPA) e ao banco de dados; também é possível identificar as classes que serão mapeadas como entidades do banco de dados.

Para definir a unidade de persistência é necessário um arquivo XML chamado persistence.xml, que deve ser criado na pasta META-INF do projeto. Por meio deste arquivo é possível definir quantas unidades de persistência for necessárias para o projeto. Exemplo de unidade de persistência mapeado para um banco de dados Oracle:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.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_1_0.xsd">
  <persistence-unit name="ExemploJPAPU" transaction-type
    ="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <class>pbc.jpa.exercicio1.modelo.Livro</class>
    <properties>
      <property name="hibernate.connection.username"
        value="usuario"/>
      <property name="hibernate.connection.password"
        value="senha"/>
      <property name="hibernate.connection.driver_class"
        value="oracle.jdbc.driver.OracleDriver"/>
      <property name="hibernate.connection.url"
        value="jdbc:oracle:thin:@localhost:1521:XE"/>
      <property name="hibernate.cache.provider_class"
        value="org.hibernate.cache.NoCacheProvider"/>
      <property name="hibernate.dialect"
        value="org.hibernate.dialect.Oracle9Dialect"/>
      <property name="hibernate.show_sql" value="true"/>
    </properties>
  </persistence-unit>
</persistence>

Neste arquivo persistence.xml a tag persistence-unit define a unidade de persistência, e na propriedade name qual seu nome (utilizado quando um EntityManager é criado por meio do EntityManagerFactory no contexto Java SE ou quando é realizado injeção de dependência através da anotação javax.persistence.PersistenceUnit no contexto Java EE). A propriedade transaction-type informa qual o tipo de transação (RESOURCE_LOCAL ou JTA). Se a aplicação é Java SE, então, utilize o tipo de transação RESOURCE_LOCAL, assim programaticamente são criadas as transações com o banco de dados e na aplicação Java EE utilize o JTA que acessa um pool de conexões em um servidor web.

Em uma unidade de persistência utilize a tag provider para informar qual a API que fornecerá uma implementação do JPA.

Em uma aplicação Java SE é necessário informar quais as classes são entidades do banco de dados através da tag class e também informar quais as propriedades necessárias para encontrar o banco de dados através da tag properties.

Nas aplicações Java EE é possível criar um pool de conexões com o banco de dados no servidor web; neste caso é aconselhado utilizar o tipo de transação Java Transaction API (JTA) que é fornecida pelo container EJB. Também é utilizada a tag jta-data-source para informar a fonte do pool de conexões (nome JNDI). Exemplo de persistence.xml para aplicações Java EE:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.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_1_0.xsd">
  <persistence-unit name="ExemploJPAPU" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>jdbc/ExemplosJPA</jta-data-source>
    <properties>
      <property name="hibernate.show_sql" value="true"/>
    </properties>
  </persistence-unit>
</persistence>

Criando uma unidade de persistência no NetBeans

O NetBeans possui uma forma mais simples de criação da unidade de persistência. Clique com o botão direito no projeto e selecione a opção Novo -> Outro..., na tela de Novo arquivo selecione a categoria Persistence e o tipo de arquivo Unidade de Persistência, conforme a figura a seguir:

Criar unidade de persistência

Clique em Próximo > para definir as propriedades do banco de dados. Na tela de Provedor e banco de dados digite um nome para a unidade de persistência, escolha qual a biblioteca de persistência, defina a conexão com o banco de dados e qual a estratégia para geração de tabelas, conforme a figura a seguir:

Criar unidade de persistência

  • O Arquivos da Unidade de Persistência é utilizado quando a EntityManager é criada. Por meio deste nome o EntityManager encontrará as configurações do banco de dados.
  • O Provedor de Persistência é a implementação do JPA utilizada para acessar o banco de dados; neste exemplo é utilizado o framework Hibernate (JPA 2.0).
  • Fonte de dados é a forma como será realizada a conexão com o banco de dados. Pode ser feito de duas maneiras, criada uma conexão direta na aplicação ou criado um pool de conexões no servidor.

Para criar uma nova conexão direta na aplicação clique na caixa de seleção Fonte de Dados e escolha a opção Nova fonte de dados..., conforme apresentado na figura a seguir:

Criar unidade de persistência

Na tela de Criar fonte de dados informe um Nome JNDI. Esse nome é usado para referenciar a conexão e também uma Conexão de banco de dados. Caso ainda não tenha uma conexão criada, escolha na caixa de seleção Conexão de banco de dados a opção Nova Conexão de Banco de Dados..., conforme apresentado na figura a seguir:

Criar unidade de persistência

Na tela Assistente de Nova Conexão escolha o Driver chamado Oracle Thin, conforme apresentado na figura a seguir:

Criar unidade de persistência

Na primeira vez que ele é usado é preciso especificar o driver do banco de dados Oracle. Clique em Adicionar e escolha o driver ojdbc6.jar, conforme a figura a seguir:

Criar unidade de persistência

Clique em Próximo para continuar a criação da conexão. Continuando a criação da Nova Conexão escolha o Nome do Driver, defina o Host (IP), Porta, ID do Serviço, Nome do usuário e Senha, conforme o exemplo da figura a seguir:

Criar unidade de persistência

Clique em Testar Conexão caso queira validar se as informações da conexão estão corretas, depois clique em Próximo para continuar e depois clique em Finalizar para terminar a criação da conexão.

Durante o desenvolvimento de uma aplicação web que acessa banco de dados, pode ser utilizado um pool de conexões que é criado pelo próprio servidor de aplicações web, ao invés de criar uma conexão com o banco de dados direto na aplicação é necessário criar um pool de conexões no servidor e depois escolher na Fonte de dados, conforme a figura a seguir:

Criar unidade de persistência

Neste exemplo será escolhida uma Fonte de Dados que foi criada no servidor GlassFish.

A Estratégia de geração de tabelas permite:

  • Criar - o JPA cria a estrutura de tabelas no banco de dados;
  • Apagar e criar – o JPA apaga a estrutura existente e cria uma estrutura nova das tabelas do banco de dados;
  • Nenhum – criar manualmente as tabelas do banco de dados.

Depois de criada a unidade de persistência, conforme apresentado na figura a seguir, note que esta é uma versão visual do arquivo persistence.xml.

Criar unidade de persistência

Este é o arquivo persistence.xml criado na pasta META-INF do projeto:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.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_1_0.xsd">
 <persistence-unit name="ExemplosJPAPU" transaction-type="JTA">
  <provider>org.hibernate.ejb.HibernatePersistence</provider>
   <jta-data-source>jdbc/Oracle</jta-data-source>
   <properties>
     <property name="hibernate.dialect"
       value="org.hibernate.dialect.Oracle9Dialect"/>
    <property name="hibernate.show_sql" value="true"/>
   </properties>
 </persistence-unit>
</persistence>

Para utilizar o Hibernate é necessário adicionar suas bibliotecas no projeto. Para fazer isso clique com o botão direito no projeto e selecione a opção Propriedades, nesta tela selecione a categoria Bibliotecas, após isso clique no botão Adicionar biblioteca... e adicione as bibliotecas JPA do Hibernate, conforme a figura a seguir:

Criar unidade de persistência

EntityManager gerenciado pela Aplicação

Nas aplicações Java SE é necessário controlar pela aplicação como deve ser criado o EntityManager, para isso precisamos fazer os seguintes passos:

1) Utilizando a classe javax.persistence.Persistence podemos utilizar o método createEntityManagerFactory() que recebe como parâmetro o nome da unidade de persistência (que veremos mais adiante) que contem as informações sobre o banco de dados para criar uma javax.persistence.EntityManagerFactory.

EntityManagerFactory factory = 
    Persistence.createEntityManagerFactory("UnitName");

2) Através do javax.persistence.EntityManagerFactory podemos utilizar o método createEntityManager() para obtermos uma EntityManager.

EntityManager entityManager = factory.createEntityManager();

Exemplo:

package pbc.jpa.exemplo.dao;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

/**
 * Classe utilizada para fazer realizar as operações
 * de banco de dados sobre a entity Livro.
 */
public class DAO {
  private EntityManager entityManager;

  public EntityManager getEntityManager() {
    EntityManagerFactory factory = 
      Persistence.createEntityManagerFactory("ExemplosJPAPU");

    entityManager = factory.createEntityManager();
    factory.close();
  }
}

No exemplo dentro do método getEntityManager() criamos um EntityManagerFactory da unidade de persistência ExemplosJPAPU (criada no item 1.2.3) através da classe Persistence, depois criamos um EntityManager a partir da factory. Quando terminamos de utilizar a EntityManagerFactory é importante chamar o método close() para liberar os recursos da factory.

EntityManager gerenciado pelo Container

No desenvolvimento de aplicações Java EE é possível deixar o contêiner EJB injetar a unidade de persistência através da anotação javax.persistence.PersistenceContext.

package pbc.jpa.exemplo.ejb;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;

/**
 * EJB utilizado para demonstrar o uso da injeção de
 * dependência do EntityManager.
 */
@Stateless
public class ExemploBean implements ExemploRemote {

    @PersistenceContext(unitName = "ExercicioJPA1PU")
    private EntityManager entityManager;

}

Este exemplo mostra um componente Session Bean Stateless que utiliza a anotação @PersistenceContext para adicionar uma unidade de persistência no EntityManager. Repare que não é preciso criar manualmente a EntityManager, pois o container EJB se encarrega de fazer isso e também atribui seu objeto para a variável com a anotação. A anotação @PersistenceContext possui o atributo unitName para informar que o nome da unidade de persistência é ExemplosJPAPU, definido na tag persistence-unit do arquivo persistence.xml.

Interface EntityManager

A interface javax.persistence.EntityManager possui a assinatura de métodos manipular as entidades, executar consultas e outros:

public void persist(Object entity);

Faz uma nova instância gerenciável e persistivel.

entityManager.persist(pessoa);

Neste exemplo o método persist da EntityManager salva a entidade Pessoa no banco de dados.

public <T> T merge(T entity);

Junta o estado da Entity com o estado persistido, por exemplo:

entityManager.merge(pessoa);

Neste exemplo o método merge da EntityManager atualiza a entidade Pessoa no banco de dados.

public void remove(Object entity);

Remove a instância da Entity do banco de dados, por exemplo:

entityManager.remove(pessoa);

Neste exemplo o método remove da EntityManager exclui a entidade Pessoa no banco de dados.

public boolean contains(Object entity);

Verifica se a instância da Entity está em um estado persistível.

public <T> T find(Class<T> entityClass, Object primaryKey);

Procura um registro no banco de dados através da Entity e id (chave primária) da tabela, caso não encontre retorna null, por exemplo:

Pessoa pessoa = entityManager.find(Pessoa.class, id);

Neste exemplo o método find da EntityManager pesquisa uma entidade pela sua classe e a chave primária.

public <T> T getReference(Class<T> entityClass, Object primaryKey);

Procura um registro no banco de dados através da Entity e id da tabela, caso não encontre retorna uma exceção javax.persistence.EntityNotFoundException.

public void flush();

Os métodos persist(), merge() e remove() aguardam a finalização da transação para sincronizar as entidades com o banco de dados, o método flush() força esta sincronização no momento em que é chamado.

public void refresh(Object entity);

Verifica se houve alguma alteração no banco de dados para sincronizar com a entidade.

public void clear();

Remove as entidades que estão no estado gerenciável dentro da EntityManager.

public void close();

Fecha a conexão do EntityManager.

public boolean isOpen();

Verifica se o EntityManager está com a conexão aberta.

public EntityTransaction getTransaction();

Obtém uma javax.persistence.EntityTransaction que é uma transação com o banco de dados.

Ciclo de vida da Entity

Uma entidade do banco de dados pode passar por quatro estados diferentes que fazem parte do seu ciclo de vida: novo, gerenciável, desacoplado e removido, conforme a figura a seguir:

Criar unidade de persistência

Ciclo de vida da entidade adaptado de BROSE, G.; SILVERMAN, M.; SRIGANESH, R. P. (2006, p.180)

Novo (new)

A Entity foi criada, mas ainda não foi persistida no banco de dados. Mudanças no estado da Entity não são sincronizadas com o banco de dados.

Gerenciado (managed)

A Entity foi persistida no banco de dados e encontra-se em um estado gerenciável. Mudanças no estado da Entity são sincronizadas com o banco de dados assim que uma transação for finalizada com sucesso.

Removido (removed)

A Entity foi agendada para ser removida da base de dados, esta entidade será removida fisicamente do banco de dados quando a transação for finalizada com sucesso.

Desacoplado (detached)

A Entity foi persistida no banco de dados, mas encontra-se em um estado que não está associada ao contexto persistível, portanto as alterações em seu estado não são refletidas na base de dados.

results matching ""

    No results matching ""