Buscar

Desenvolvimento de Software para WEB

Prévia do material em texto

Desenvolvimento de Software 
para WEB 
 
JPA – Java Persistence API 
Prof. Regis Pires Magalhães 
regismagalhaes@ufc.br 
Problema 
POO – Programação Orientada a Objetos 
x 
BDR – Banco de Dados Relacionais 
= 
Paradigmas Diferentes 
JDBC 
• Trabalha no mesmo nível do banco de dados. 
MOR – Mapeamento Objeto 
Relacional 
• Também chamado de ORM 
▫ Object Relational Mapping 
• Resolve o famoso problema de “descompasso de 
impedância” (impedance mismatch) entre os 
mundos objeto e relacional. 
• Pode ser usado para gerar as tabelas no banco de 
dados ou atualizar as restrições de integridade. 
MOR – Mapeamento Objeto 
Relacional 
• O melhor dos dois mundos: 
▫ Modelo Orientado a Objetos; 
▫ Performance e confiabilidade dos bancos de dados 
relacionais. 
JPA - Características 
• Portabilidade 
• Persistência transparente 
▫ Não há necessidade de implementação de interfaces 
especiais ou classes base. Usa POJOs – Plain Old Java 
Objetcs. 
▫ Atributos são persistidos. 
▫ Não há necessidade de geração de código. 
▫ Suporta tipos definidos pelo usuário 
▫ Controle transparente de restrições de integridade 
• Consulta orientada a objetos ou não 
▫ Query by Criteria 
▫ JPQL 
▫ Consultas dinâmicas e nomeadas 
▫ SQL Nativo 
JPA 
• Definida na JSR-220 (Java Specification 
Requests) que especificou o EJB 3.0 (Enterprise 
JavaBeans 3.0) 
▫ Padroniza o mapeamento Objeto-Relacional em 
Java. 
• Solução completa para MOR e persistência de 
dados: 
▫ Modo declarativo de descrever mapeamento O/R; 
▫ Linguagem de consulta (JPQL); 
▫ Ferramentas para manipular entidades. 
JPA 
Implementações de JPA 
• Algumas implementações de JPA: 
▫ Hibernate 
▫ Oracle TopLink 
 É a implementação de referência usada pela Sun 
 Mais enxuto e menor que o Hibernate: apenas 2 jars 
são necessários 
▫ EclipseLink 
▫ Apache OpenJPA 
▫ Kodo 
 EJB + JDO 
Hibernate 
• Poderoso framework de mapeamento objeto-
relacional (MOR); 
• Framework de Persistência; 
• Excelente performance; 
• É a mais popular ferramenta de MOR da 
atualidade; 
• Software Livre e Gratuito; 
• Permite o uso de uma grande variedade de 
SGBDs; 
• Não é um padrão de indústria. 
Hibernate 
Hibernate 
• Onde baixar? 
▫ http://sourceforge.net/projects/hibernate/files/hibernate4/ 
 
Hibernate – O que usar 
• lib/required 
▫ antlr-2.7.7.jar 
▫ dom4j-1.6.1.jar 
▫ hibernate-commons-annotations-4.0.2.Final.jar 
▫ hibernate-core-4.2.3.Final.jar 
▫ hibernate-jpa-2.0-api-1.0.1.Final.jar 
▫ javassist-3.15.0-GA.jar 
▫ jboss-logging-3.1.0.GA.jar 
▫ jboss-transaction-api_1.1_spec-1.0.1.Final.jar 
• lib/jpa 
▫ hibernate-entitymanager-4.2.3.Final.jar 
Hibernate – O que usar 
• Driver JDBC do SGBD 
▫ Exemplos: 
 PostgreSQL: postgresql-9.2-1002.jdbc4.jar 
 MySQL: mysql-connector-java-5.1.20.jar 
 H2: h2-1.3.166.jar 
Hibernate – Dependências via Maven 
... 
<dependencies> 
<dependency> 
<groupId>javax.validation</groupId> 
<artifactId>validation-api</artifactId> 
<version>1.1.0.Final</version> 
</dependency> 
<dependency> 
<groupId>org.hibernate</groupId> 
<artifactId>hibernate-core</artifactId> 
<version>4.3.1.Final</version> 
</dependency> 
<dependency> 
<groupId>org.hibernate</groupId> 
<artifactId>hibernate-entitymanager</artifactId> 
<version>4.3.1.Final</version> 
</dependency> 
<dependency> 
<groupId>postgresql</groupId> 
<artifactId>postgresql</artifactId> 
<version>9.1-901.jdbc4</version> 
</dependency> 
</dependencies> 
... 
Hibernate/JPA – Complementos 
lib/optional 
Connection Pool 
c3p0 
proxool 
Cache de Segundo Nível 
ehcache 
infinispan 
Hibernate x JPA 
JPA provê um subconjunto das 
funcionalidades do Hibernate. 
Então, porque usar JPA? 
Padrão de indústria 
Independência de implementação 
Não há necessidade de se listar todas as classes 
anotadas em um arquivo de configuração. 
... 
JPA - Principais Conceitos 
• EntityManager 
▫ responsável por praticamente todas operações de 
persistência de objetos 
• PersistenceContext 
▫ área de memória que mantém os objetos que estão 
sendo manipulados pelo EntityManager 
• Provedores: 
▫ A especificação é implementada por diversos 
fabricantes. 
• Persistence Unit 
▫ Configuração do provedor JPA para localizar o 
banco de dados e estabelecer conexões JDBC. 
Persistence Unit 
• src/META-INF/persistence.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="dev" transaction-type="RESOURCE_LOCAL"> 
 <properties> 
 <property name="javax.persistence.jdbc.url" 
 value="jdbc:postgresql://localhost/aula-jpa" /> 
 <property name="javax.persistence.jdbc.driver" 
 value="org.postgresql.Driver" /> 
 <property name="javax.persistence.jdbc.user" 
 value="postgres" /> 
 <property name="javax.persistence.jdbc.password" 
 value="postgres" /> 
 
 <property name="hibernate.hbm2ddl.auto" value="update" /> 
 <property name="hibernate.show_sql" value="true" /> 
 <property name="hibernate.format_sql" value="true" /> 
 </properties> 
 </persistence-unit> 
</persistence> 
JPA – Mapeamento 
Classes e interfaces estão no pacote: 
javax.persistence 
Uso anotações – @ 
Configuração por exceção 
JPA – Mapeamento via anotações 
@Entity 
public class Contato { 
 
 public Contato() { 
 super(); 
 } 
 
 public Contato(String nome, String fone) { 
 super(); 
 this.nome = nome; 
 this.fone = fone; 
 } 
 
 @Id 
 @GeneratedValue(strategy=GenerationType.IDENTITY) 
 private int id; 
 
 private String nome; 
 
 private String fone; 
 
 // Getters e Setters 
} 
Funciona bem no: 
• MySQL 
• PostgreSQL 
• H2 
• ... 
Inserindo dados via JPA 
public class InsereDados { 
 
 public static void main(String[] args) { 
 EntityManagerFactory emf = 
 Persistence.createEntityManagerFactory("dev"); 
 EntityManager em = emf.createEntityManager(); 
 EntityTransaction tx = em.getTransaction(); 
 try { 
 tx.begin(); 
 em.persist(new Contato("João", "(88)3452-4567")); 
 em.persist(new Contato("Maria", "(88)3452-4568")); 
 em.persist(new Contato("José", "(88)3452-4569")); 
 tx.commit(); 
 } catch (Exception e) { 
 tx.rollback(); 
 e.printStackTrace(); 
 } finally { 
 em.close(); 
 } 
 } 
} 
Formas de Consultas 
Há basicamente 3 formas de realizar 
consultas: 
JPQL (Java Persistence QL) 
Várias melhorias em relação à EJBQL. 
Criteria Query 
Nativas (SQL) 
As consultas JPQL ou Nativas podem ser: 
Dinâmicas 
Nomeadas (NamedQuery) 
 
Consultando dados via JPQL 
public class Principal { 
 
 public static void main(String[] args) { 
 EntityManagerFactory emf = 
 Persistence.createEntityManagerFactory("dev"); 
 EntityManager em = emf.createEntityManager(); 
 
 List<Contato> l = em.createQuery("from Contato", 
 Contato.class).getResultList(); 
 
 for (Contato c : l) { 
 System.out.println("Nome: " + c.getNome()); 
 } 
 
 em.close(); 
 } 
} 
Consultando dados via CriteriaQuery 
public class Principal2 { 
 
 public static void main(String[] args) { 
 EntityManagerFactory emf = 
 Persistence.createEntityManagerFactory("dev"); 
 EntityManager em = emf.createEntityManager(); 
 
 CriteriaBuilder cb = em.getCriteriaBuilder(); 
 CriteriaQuery<Contato> cq = cb.createQuery(Contato.class); 
 cq.from(Contato.class); 
 List<Contato> l = em.createQuery(cq).getResultList(); 
 
 for (Contato c : l) { 
 System.out.println("Nome: " + c.getNome()); 
 } 
 
 em.close(); 
 } 
} 
Criteria encapsula as cláusulas de 
uma consulta tradicional 
Definições de Named Queries 
@Entity 
@NamedQueries({ 
 @NamedQuery(name="Contato.findContato", 
 query="from Contato") 
}) 
public class Contato { 
 
 public Contato() { 
 super(); 
 } 
 
 public Contato(String nome, String fone) { 
 super(); 
 this.nome = nome; 
 this.fone = fone; 
 } 
 
 @Id 
 @GeneratedValue(strategy=GenerationType.IDENTITY) 
 private int id; 
... 
} 
Consultando dados via Named Query 
public class Principal3 { 
 
 public static void main(String[] args) { 
 EntityManagerFactory emf = 
 Persistence.createEntityManagerFactory("dev"); 
 EntityManager em = emf.createEntityManager(); 
 
 List<Contato> l = em.createNamedQuery("Contato.findContato", 
 Contato.class).getResultList(); 
 
 for (Contato c : l) { 
 System.out.println("Nome: " + c.getNome()); 
 } 
 
 em.close(); 
 } 
} 
JPQL ou Criteria? 
• Qualquer consulta definida com JPQL pode ser definida com Criteria e vice-versa. 
• Algumas consultas são mais facilmente definidas em JPQL, enquanto outras são 
mais facilmente definidas em Criteria. 
• Consultas sem filtros ou com filtros fixos são mais facilmente definidas com JPQL. 
• Consultas com filtros variáveis são mais facilmente definidas com Criteria. 
• A tipagem usada em Criteria é verificada em tempo de compilação (tipagem 
segura). 
• Criteria geralmente possui melhor desempenho comparado com consultas 
dinâmicas usando JPQL. 
• A API de Criteria é relativamente complexa e o código não fica muito legível. 
• Named queries são checadas quando o contexto JPA é iniciado. 
▫ Consultas checadas durante a inicialização da aplicação (+ segurança, inicialização + 
lenta). 
 
 
 
Centralizando a criação e 
fechamento do EntityManager 
• Até agora, cada classe que usava JPA especificava um 
PersistenceUnit e criava um EntityManager. 
• Toda vez que era necessário alterar o persistence unit, 
tínhamos que alterar cada classe. 
• Uma melhoria que pode ser realizada é a centralização 
da definição do PersistenceUnit a ser usado. 
ThreadLocal 
• Em aplicações WEB toda requisição gera uma nova 
Thread no servidor. 
• Muitas vezes é necessário usar o EntityManager em 
várias partes da aplicação. 
• Para facilitar essa tarefa, pode-se associar o 
EntityManager à Thread da requisição. 
• ThreadLocal é uma funcionalidade do Java que permite 
armazenar um objeto em um Map em que a chave é a 
Thread em uso e o valor, o objeto. 
▫ O método set associa o objeto à Thread atual. 
▫ O método get obtém o objeto que está associado à 
Thread atual. 
ThreadLocal 
import javax.persistence.*; 
 
public class JPAUtil { 
 private static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("dev-h2"); 
 
 private static ThreadLocal<EntityManager> ems = new ThreadLocal<EntityManager>(); 
 
 /** 
 * Obtém o EntityManager vinculado à Thread atual. Se não existir, é criado e vinculado à Thread atual. 
 */ 
 public static EntityManager getEntityManager() { 
 EntityManager em = ems.get(); 
 if (em == null) { 
 em = emf.createEntityManager(); 
 ems.set(em); 
 } 
 return em; 
 } 
 
 /** 
 * Fecha o EntityManager atrelado à Thread atual e retira-o da ThreadLocal. 
 */ 
 public static void closeEntityManager() { 
 EntityManager em = ems.get(); 
 if (em != null) { 
 EntityTransaction tx = em.getTransaction(); 
 if (tx.isActive()) { 
 tx.commit(); 
 } 
 em.close(); 
 ems.set(null); 
 } 
 } 
 ... 
ThreadLocal 
 
 ... 
 
 public static void beginTransaction() { 
 getEntityManager().getTransaction().begin(); 
 } 
 
 public static void commit() { 
 EntityTransaction tx = getEntityManager().getTransaction(); 
 if (tx.isActive()) { 
 tx.commit(); 
 } 
 } 
 
 public static void rollback() { 
 EntityTransaction tx = getEntityManager().getTransaction(); 
 if (tx.isActive()) { 
 tx.rollback(); 
 } 
 } 
} 
InsereDados com JPAUtil 
public class InsereDados { 
 
 public static void main(String[] args) { 
 EntityManager em = JPAUtil.getEntityManager(); 
 EntityTransaction tx = em.getTransaction(); 
 try { 
 tx.begin(); 
 em.persist(new Contato("João", "(88)3452-4567")); 
 em.persist(new Contato("Maria", "(88)3452-4568")); 
 em.persist(new Contato("José", "(88)3452-4569")); 
 tx.commit(); 
 } catch (Exception e) { 
 tx.rollback(); 
 e.printStackTrace(); 
 } finally { 
 JPAUtil.closeEntityManager(); 
 } 
 } 
} 
JPQL com JPAUtil 
public class PrincipalJPQL { 
 
 public static void main(String[] args) { 
 EntityManager em = JPAUtil.getEntityManager(); 
 
 // Consulta usando JPQL 
 List<Contato> l = em.createQuery("from Contato", 
 Contato.class).getResultList(); 
 for (Contato c : l) { 
 System.out.println("Nome: " + c.getNome()); 
 } 
 
 JPAUtil.closeEntityManager(); 
 } 
 
} 
Criteria com JPAUtil 
public class PrincipalCriteria { 
 
 public static void main(String[] args) { 
 EntityManager em = JPAUtil.getEntityManager(); 
 
 // Consulta usando Criteria Query 
 CriteriaBuilder cb = em.getCriteriaBuilder(); 
 CriteriaQuery<Contato> cq = cb.createQuery(Contato.class); 
 cq.from(Contato.class); 
 List<Contato> l = em.createQuery(cq).getResultList(); 
 
 for (Contato c : l) { 
 System.out.println("Nome: " + c.getNome()); 
 } 
 JPAUtil.closeEntityManager(); 
 } 
 
} 
NamedQuery com JPAUtil 
public class PrincipalNamedQuery { 
 
 public static void main(String[] args) { 
 EntityManager em = JPAUtil.getEntityManager(); 
 
 // Consulta usando Named Query 
 List<Contato> l = em.createNamedQuery("Contato.findContato", 
 Contato.class).getResultList(); 
 for (Contato c : l) { 
 System.out.println("Nome: " + c.getNome()); 
 } 
 
 JPAUtil.closeEntityManager(); 
 } 
 
} 
Padrão de projeto: DAO 
• DAO – Data Access Object. 
• Fornece uma interface padrão de acesso a dados, 
independente da tecnologia utilizada. 
• Permite que uma entidade que solicita a manipulação de 
dados os utilize mesmo sem ter noção sobre a tecnologia que 
permite o armazenamento persistente. 
• Consiste em: 
▫ Uma interface que abstraia a tecnologia de 
armazenamento. 
 Usualmente o nome da interface possui o sufixo DAO. 
▫ Classe(s) concreta(s) que implementa(m) a interface DAO. 
Padrão de projeto: DAO 
package br.ufc.dsweb.dao; 
 
import java.util.List; 
 
public interface GenericDAO<T> { 
 public void save(T entity); 
 public void delete(T entity); 
 public T find(Object id); 
 public List<T> find();public void beginTransaction(); 
 public void commit(); 
 public void rollback(); 
 public void close(); 
} 
Padrão de projeto: DAO 
public abstract class GenericJPADAO<T> implements GenericDAO<T> { 
 
 protected Class<T> persistentClass; 
 
 public void save(T entity) { 
 getEm().merge(entity); 
 } 
 
 public void delete(T entity) { 
 getEm().remove(getEm().merge(entity)); 
 } 
 
 public T find(Object id) { 
 return getEm().find(persistentClass, id); 
 } 
 
 public List<T> find() { 
 CriteriaQuery<T> cq = getEm().getCriteriaBuilder().createQuery(persistentClass); 
 cq.from(persistentClass); 
 return getEm().createQuery(cq).getResultList(); 
 } 
 ... 
Padrão de projeto: DAO 
public abstract class GenericJPADAO<T> implements GenericDAO<T> { 
 ... 
 public EntityManager getEm() { 
 return JPAUtil.getEntityManager(); 
 } 
 
 public void beginTransaction() { 
 JPAUtil.beginTransaction(); 
 } 
 
 public void commit() { 
 JPAUtil.commit(); 
 } 
 
 public void rollback() { 
 JPAUtil.rollback(); 
 } 
 
 public void close() { 
 JPAUtil.closeEntityManager(); 
 } 
} 
Padrão de projeto: DAO 
public interface ContatoDAO extends GenericDAO<Contato> { 
 
} 
public class ContatoJPADAO extends GenericJPADAO<Contato> 
 implements ContatoDAO { 
 
 public ContatoJPADAO() { 
 this.persistentClass = Contato.class; 
 } 
 
} 
Padrão de projeto: DAO 
Acrescentando novos métodos ao DAO específico. 
InsereDados com DAO 
public class InsereDados { 
 
 public static void main(String[] args) { 
 ContatoDAO contatoDAO = new ContatoJPADAO(); 
 try { 
 contatoDAO.beginTransaction(); 
 contatoDAO.save(new Contato("João", "(88)3452-4567")); 
 contatoDAO.save(new Contato("Maria", "(88)3452-4568")); 
 contatoDAO.save(new Contato("José", "(88)3452-4569")); 
 contatoDAO.commit(); 
 } catch (Exception e) { 
 contatoDAO.rollback(); 
 e.printStackTrace(); 
 } finally { 
 contatoDAO.close(); 
 } 
 } 
} 
Consulta dados com DAO 
public class Principal { 
 
 public static void main(String[] args) { 
 ContatoDAO contatoDAO = new ContatoJPADAO(); 
 
 List<Contato> l = contatoDAO.find(); 
 
 for (Contato c : l) { 
 System.out.println("Nome: " + c.getNome()); 
 } 
 contatoDAO.close(); 
 } 
 
} 
Mapeamento via Anotações 
import javax.persistence.*; 
 
@Entity 
@Table(name = "MESSAGES") 
public class Message { 
 
 @Id 
 @GeneratedValue 
 @Column(name = "MESSAGE_ID") 
 private Long id; 
 
 @Column(name = "MESSAGE_TEXT") 
 private String text; 
 
 public Message(String text) { 
 this.text = text; 
 } 
 
 // Getters and Setters... 
} 
Anotações comuns 
@Entity 
@Table 
Por padrão, a JPA assume que todos os campos 
persistentes de uma entidade serão 
armazenados em uma tabela com o mesmo 
nome da entidade. 
@Table(name="FUN") 
@Column 
Por padrão, a JPA assume que o nome de cada 
atributo corresponde ao mesmo nome na tabela 
@Column(name="FUN_ID") 
@Id 
Anotações Comuns 
@GeneratedValue 
geração automática de identificadores 
@Temporal 
para informações relacionadas ao tempo 
(DATE, TIME e TIMESTAMP) 
@OneToOne 
@OneToOne(optional=false) 
@JoinColumn(name=“ADDRESS_ID”, 
 unique=true, nullable=false) 
Query Address getAddress() { ... } 
Geração de Chave Primária 
AUTO 
@Id @GeneratedValue(strategy=GenerationType.AUTO) 
IDENTITY 
@Id @GeneratedValue(strategy=GenerationType.IDENTITY) 
SEQUENCE 
@Id @GeneratedValue(strategy=GenerationType.SEQUENCE) 
TABLE 
@Id @GeneratedValue(strategy=GenerationType.TABLE) 
Geração de Chave Primária 
As opções para geração de chave primária são estas: 
AUTO 
@Id @GeneratedValue(strategy=GenerationType.AUTO) 
private int id; 
IDENTITY 
@Id @GeneratedValue(strategy=GenerationType.IDENTITY) 
private int id; 
SEQUENCE 
@Entity 
@SequenceGenerator(name="SEQUENCE", sequenceName="person_id_seq") 
public class Person { 
 @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, 
 generator="SEQUENCE") 
 private Integer id; 
 ... 
} 
Geração de Chave Primária 
TABLE 
@Entity 
public class Inventory implements Serializable { 
@Id 
@GeneratedValue(generator="InvTab") 
@TableGenerator(name="InvTab", table="ID_GEN", 
 pkColumnName="ID_NAME", valueColumnName="ID_VAL", 
 pkColumnValue="INV_GEN") 
private long id; 
NONE – é o padrão. De nada for dito, não haverá 
geração automática de chave primária. A 
geração passa a ser responsabilidade da aplicação. 
 
A estratégia mais portável entre os diferentes bancos 
de dados é TABLE. 
Hibernate 
Comparação de termos com o JPA: 
Hibernate → JPA 
SessionFactory → EntityManagerFactory 
Session → EntityManager 
Query → Query 
Transaction → EntityTransaction 
Hibernate 
Propriedades: 
hibernate.hbm2ddl.auto 
create – apaga as tabelas mapeadas e depois as 
recria. 
create-drop – cria as tabelas mapeadas e ao 
fechar o EntityManager, remove-as. 
update – usa SchemaUpdate para evolução da 
base de dados de acordo com o que está 
mapeado nas classes. 
validate – usa SchemaValidate para comparar o 
que está no banco com o que está mapeado. 
none (default) 
Parâmetros de Consultas 
• Os parâmetros de consultas podem ser 
nomeados ou numerados. 
@NamedQuery(name="findEmployeesAboveSal", 
 query="SELECT e " + 
 "FROM Employee e " + 
 "WHERE e.department = :dept AND " + 
 " e.salary > :sal") 
Parâmetros Nomeados 
@NamedQuery(name="findEmployeesAboveSal", 
 query="SELECT e " + 
 "FROM Employee e " + 
 "WHERE e.department = :dept AND " + 
 " e.salary > :sal") 
public class EmployeeServiceBean implements EmployeeService { 
 @PersistenceContext(unitName="EmployeeService") 
 EntityManager em; 
 public List findEmployeesAboveSal(Department dept, long minSal) { 
 return em.createNamedQuery("findEmployeesAboveSal") 
 .setParameter("dept", dept) 
 .setParameter("sal", minSal) 
 .getResultList(); 
 } 
 // ... 
} 
Parâmetros Numerados 
public class EmployeeServiceBean implements EmployeeService { 
 @PersistenceContext(unitName="EmployeeService") 
 EntityManager em; 
 public List findEmployeesHiredDuringPeriod(Date start, Date end) { 
 return em.createQuery("SELECT e " + 
 "FROM Employee e " + 
 "WHERE e.startDate BETWEEN ?1 AND ?2") 
 .setParameter(1, start, TemporalType.DATE) 
 .setParameter(2, end, TemporalType.DATE) 
 .getResultList(); 
 } 
 // ... 
} 
 
Consultas 
public class ProdutoDAO ... 
 . . . 
 
 public Produto findByName(final String nome) { 
 Produto temp = null; 
 try { 
 temp = (Produto) em.createQuery( 
 "SELECT p FROM Produto p WHERE p.nome LIKE :nome") 
 .setParameter("nome", nome + "%").getSingleResult(); 
 } catch(Exception e) { 
 e.printStackTrace(); 
 } 
 return temp; 
 } 
 } 
 
 . . . 
} 
Consultas Nomeadas 
@Entity 
@Table(name = "produtos") 
@NamedQueries( { 
 @NamedQuery(name = "Produto.findByDescricao", 
 query = "SELECT p FROM Produto p WHERE p.descricao = " 
 + ":descricao"), 
 @NamedQuery( 
 name = "Produto.findByPreco", 
 query = "SELECT p FROM Produto p WHERE p.preco = ?1") 
} ) 
public class Produto implements Serializable { 
 . . . // Implementação do Entity Bean. 
} 
Consultas Nomeadas 
public class ProdutoDAO ... 
. . . 
 
 public List<Produto> findByPreco(final BigDecimal preco) { 
 return em.createNamedQuery("Produto.findByPreco") 
 .setParameter(1, preco).getResultList(); 
 } 
 
. . . 
} 
Paginação em Consultas 
• Métodos setFirstResult() e setMaxResults() 
List l = em.createQuery("select c from Cliente c") 
 .setFirstResult(100).setMaxResults(10) 
 .getResultList(); 
JPA 2 
• JPA 2 tem suporte a validadores nos beans. 
▫ Parecido com o Hibernate Validador. 
 
public class Aluno { 
 @NotNull 
 private String nome; 
 
 @Length(max = 10) 
 @NotNull 
 public String endereco 
Obtenção de EntityManager 
Container-managed 
O container abre e fecha o entity manager. Além disso, 
ainda fica responsável pelos limites das transações. 
Obtenção via injeção de dependência ou JNDI. 
Via injeção de dependência: 
@PersistenceContext 
private EntityManager em; 
Via JNDI: 
EntityManager em = (EntityManager) 
ctx.lookup("java:comp/env/accounting"); 
Application-managed 
EntityManager gerenciado via código. 
EntityManagerFactory emf = Persistence.createEntityManagerFactory( 
"jpa-hibernate-derby"); 
EntityManager em = emf.createEntityManager(); 
Mapeamento de membros não 
persistidos 
Membros que não são persistidos devem ser 
anotados como transientes. 
@Transient 
private int idade; 
Associações 
As anotações usadas para definir os tipos de 
associações são essas: 
@OneToOne 
@ManyToOne 
@OneToMany 
@ManyToMany 
Associações one-to-one 
@Entity 
public class Customer implements Serializable { 
 ... 
 @OneToOne 
 @JoinColumn(name="CUSTREC_ID", unique=true, 
 nullable=false, updatable=false) 
 public CustomerRecord getCustomerRecord() { 
 return customerRecord; 
 } 
 ... 
} 
@Entity 
public class CustomerRecord implements Serializable { 
 ... 
 @OneToOne(mappedBy="customerRecord") 
 public Customer getCustomer() { 
 return customer; 
 } 
 ... 
} 
Associações one-to-one 
Em associações one-to-one bidirecionais, usamos o 
atributo mappedBy para explicitar o lado não 
proprietário (inverso) da associação. 
O lado proprietário da associação em relacionamentos 
one-to-one e one-to-many é o lado que possui a 
chave estrangeira (foreign key). 
 
Associações unidirecionais e bidirecionais 
• Associação unidirecional 
▫ Possui somente o lado proprietário da associação. 
• Associação bidirecional 
▫ Possui um lado proprietário e um lado não proprietário 
(inverso) da associação. 
▫ O lado não proprietário (inverso) da associação deve fazer 
referência ao lado proprietário através do uso do elemento 
mappedBy da anotação OneToOne, OneToMany ou 
ManyToMany. 
▫ mappedBy define o nome do atributo do lado proprietário 
da associação. 
• Lado proprietário da associação 
▫ Determina as atualizações ao relacionamento no banco de 
dados. 
Associações one-to-many e many-to-one 
@Entity 
public class Customer implements Serializable { 
 ... 
 @OneToMany(cascade=ALL, mappedBy="customer") 
 public Set<Order> getOrders() { 
 return orders; 
 } 
 ... 
} 
@Entity 
public class Order implements Serializable { 
 ... 
 @ManyToOne 
 @JoinColumn(name="CUST_ID", nullable=false) 
 public Customer getCustomer() { 
 return customer; 
 } 
 ... 
} 
Associações one-to-many 
e many-to-one 
@Entity 
public class Company { 
 @OneToMany(fetch = FetchType.LAZY, mappedBy = "company") 
 private List<Branch> branches; 
} 
@Entity 
public class Branch { 
 
@ManyToOne(fetch = FetchType.LAZY) 
 @JoinColumn(name = "companyId") 
 private Company company; 
} 
 
Associações one-to-many 
e many-to-one 
Em caso de associações bidirecionais, em uma classe 
temos um atributo OneToMany e na outra classe (a 
que detém a chave estrangeira) temos um atributo 
ManyToOne. 
No lado OneToMany de uma associação bidirecional, 
usamos o atributo mappedBy para explicitar que o 
relacionamento (chave estrangeira) fica no lado 
oposto (inverso) da associação. 
O lado ManyToOne é o lado proprietário e, portanto, 
não pode ter o elemento mappedBy. 
Associações many-to-many 
@Entity 
public class Customer implements Serializable { 
 ... 
 @ManyToMany 
 @JoinTable( 
 name="CUST_PHONE", 
 joinColumns= 
 @JoinColumn(name="CUST_ID", referencedColumnName="ID"), 
 inverseJoinColumns= 
 @JoinColumn(name="PHONE_ID", referencedColumnName="ID") 
 ) 
 public Set<PhoneNumber> getPhones() { 
 return phones; 
 } 
 ... 
} 
Associações many-to-many 
Em associações many-to-many, qualquer lado pode 
ser escolhido para ser o lado proprietário da 
associação. 
@Entity 
public class PhoneNumber implements Serializable { 
 ... 
 @ManyToMany(mappedBy="phones") 
 public Set<Customer> getCustomers() { 
 return customers; 
 } 
 ... 
} 
Associações many-to-many 
• Se for necessário criar atributos na tabela de 
junção, deve-se criar uma nova classe com os 
novos atributos. 
Associações many-to-many 
class User { 
 @OneToMany(mappedBy = "user") 
 private Set<UserService> userServices = new HashSet<UserService>(); 
} 
 
class UserService { 
 @ManyToOne @JoinColumn(name = "user_id") 
 private User user; 
 
 @ManyToOne @JoinColumn(name = "service_code") 
 private Service service; 
 
 @Column(name = "blocked") 
 private boolean blocked; 
} 
 
class Service { 
 @OneToMany(mappedBy = "service") 
 private Set<UserService> userServices = new HashSet<UserService>(); 
} 
Cascateamento 
Cascateamento pode ser usado para propagar operações 
para classes associadas. 
Tipos: 
ALL – Todas as operações possíveis são cascateadas para as 
classes associadas. 
MERGE – Se a entidade fonte estiver “merged”, o merge é 
cascateado para as classes associadas. 
PERSIST – Se a entidade fonte for persistida, a presistência é 
cascateada para as classes associadas. 
REFRESH – Se a entidade fonte for atualizada, a atualização é 
cascateada para as classes associadas. 
REMOVE – Se a entidade fonte for removida, as classes 
associadas também serão removidas. 
Exemplo: 
@OneToMany(cascade={CascadeType.REMOVE}) 
private List<Pessoa> dependentes; 
Carregamento de Associações 
A associações podem ser carregadas de duas formas: 
EAGER – A associação é carregada juntamente com a 
classe base. 
@OneToMany(fetch=FetchType.EAGER) 
LAZY – A associação somente é carregada quando for 
usada. 
@OneToMany(fetch=FetchType.LAZY) 
Em associações ManyToOne e OneToOne, EAGER é 
padrão. 
Em associações OneToMany e ManyToMany, LAZY é 
padrão. 
As coleções só são inicializadas quando houver 
necessidade. 
Apenas quando algum método que acesse o conteúdo da 
coleção for executado é que ela será preenchida. 
Carregamento de Associações 
Definição de um atributo comum como LAZY: 
@Entity 
public class Book implements Serializable { 
 ... 
 @Basic(fetch=LAZY) 
 protected String toc; 
 ... 
} 
Carregamento de Associações 
Relacionamentos LAZY podem poupar recursos, 
principalmentequando há muitos modelos na 
aplicação. 
No entanto, requerem cuidados como manter a 
sessão aberta. 
Modo de Carregamento 
@Fetch é uma anotação do Hibernate usada no 
relacionamento que informa como criar o comando 
SQL. 
A anotação recebe a enumeração FetchMode 
(SELECT, JOIN ou SUBSELECT). 
FetchMode.SELECT – realiza selects separados para 
buscar os dados. 
FetchMode.JOIN – cria um único comando SQL que 
busca todas as informações de uma única vez através 
de cláusulas join. 
FetchMode.SUBSELECT – executa subconsultas, se o 
banco tem suporte para essa funcionalidade. 
Herança 
JPA disponibiliza 3 estratégias para o uso de herança: 
SINGLE_TABLE – É a opção default. Há uma única tabela para toda 
a herarquia de classes. 
Há uma coluna na tabela para determinar a classe 
(DiscriminatorColumn). 
JOINED – Define que há uma tabela para cada classe da hierarquia de 
classes. 
Atributos de uma superclasse são persistidos na tabela da 
superclasse. 
Assim, para obter um objeto de uma subclasse, é necessário fazer 
um join envolvendo todas as tabelas das superclasses. Isso pode 
ser bastante oneroso para o banco de dados e 
comprometer a performance da aplicação, especialmente 
quando a hierarquia é complexa e composta de muitas 
classes. 
Há uma coluna na tabela da classe base para determinar a classe 
(DiscriminatorColumn) 
Herança 
▫ TABLE_PER_CLASS – Semelhante à estratégia 
JOINED, mas cada tabela possui os campos dos 
atributos herdados e os campos dos seus próprios 
atributos (não herdados). 
Herança - SINGLE_TABLE 
@Entity 
@Table(name="PROJECT") 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name="TYPE", 
 discriminatorType=DiscriminatorType.STRING,length=20) 
@DiscriminatorValue("P") 
public class Project { 
 @Id protected BigInteger id; 
 protected String description; 
 ... 
 
} 
@Entity 
@DiscriminatorValue("L") 
public class LargeProject extends Project { 
 protected BigInteger budget; 
 ... 
} 
Herança - JOINED 
@Entity 
@Table(name="PROJECT") 
@Inheritance(strategy=InheritanceType.JOINED) 
@DiscriminatorColumn(name="TYPE", 
discriminatorType=DiscriminatorType.STRING,length=20) 
@DiscriminatorValue("P") 
public class Project { 
 @Id protected BigInteger id; 
 protected String description; 
 ... 
} 
@Entity 
@Table(name="L_PROJECT") 
@DiscriminatorValue("L") 
public class LargeProject extends Project { 
 protected BigInteger budget; 
 ... 
} 
Herança - MappedSuperclass 
É possível determinar uma superclasse da qual uma 
entidade herda atributos persistentes através da 
anotação @MappedSuperclass. 
Recurso interessante quando várias classes 
compartilham atributos persistentes. 
Pode-se usar as anotações @AttributeOverride ou 
@AssociationOverride na subclasse para 
sobrescrever a configuração da superclasse. 
Herança - MappedSuperclass 
@MappedSuperclass 
public class Employee { 
 @Id 
 protected Integer empId; 
 
 @Version 
 protected Integer version; 
 
 @ManyToOne 
 @JoinColumn(name="ADDR") 
 protected Address address; 
 ... 
} 
@Entity 
@AttributeOverride(name="address", column=@Column(name="ADDR_ID")) 
public class PartTimeEmployee extends Employee { 
 @Column(name="WAGE") 
 protected Float hourlyWage; 
 ... 
} 
Composição – Classes Embutidas 
• JPA permite o mapeamento de objetos 
embutidos. 
• Cada atributo do objeto embutido é mapeado 
para a tabela da entidade base. 
• Isso permite trabalhar com mais de uma classe, 
usando composição e armazenando tudo em 
uma única tabela. 
Composição – Classes Embutidas 
@Embeddable 
// Não persistente 
public class Intervalo { 
 private int inicio; 
 private int fim; 
 ... 
} 
@Embedded 
@AttributeOverrides({ 
@AttributeOverride(name="inicio", 
 column=@Column(name="VALOR_INICIAL")), 
@AttributeOverride(name="fim", 
 column=@Column(name="VALOR_FINAL")) 
}) 
Intervalo getIntervalo() { ... } 
Connection Pool 
• Conexão é um recurso caro demais para ficar 
criando e fechando o tempo todo. 
• Um pool é uma reserva de objetos prontos para 
serem usados, em vez de demandar a criação de 
novos objetos sempre que precisarmos. 
• O Hibernate tem integração nativa com o pool 
c3p0. 
Connection Pool 
<persistence...> 
 <persistence-unit name="default" transaction-type="RESOURCE_LOCAL"> 
 ... 
 <properties> 
 <property name="javax.persistence.jdbc.url" value="..." /> 
 <property name="javax.persistence.jdbc.driver" 
 value="..." /> 
 <property name="javax.persistence.jdbc.user" value="..." /> 
 <property name="javax.persistence.jdbc.password" 
 value="..." /> 
 <property name="hibernate.c3p0.min_size" value="5" /> 
 <property name="hibernate.c3p0.max_size" value="20" /> 
 <property name="hibernate.c3p0.timeout" value="300" /> 
 <property name="hibernate.c3p0.max_statements" value="50" /> 
 ... 
 </properties> 
 </persistence-unit> 
</persistence> 
Cache 
• JPA possui dois níveis de cache que são usados 
para diminuir os acessos ao banco de dados: 
▫ Cache de primeiro nível. 
▫ Cache de segunda nível. 
• O cache de primeiro nível é usado 
automaticamente no contexto JPA. 
• Cada objeto que é carregado pelo EntityManager 
acaba ficando no cache desse EntityManager. 
• A partir de então, toda vez que o mesmo objeto 
for buscado pela chave, ele será devolvido 
imediatamente, sem necessidade de um novo 
acesso ao banco para isso. 
Cache de primeiro nível 
• Ao invés de realizar atualizações a cada comando 
dentro de uma transação, as atualizações são 
feitas somente ao final da transação. 
▫ Exemplo: Se um objeto é modificado várias vezes 
dentro de uma transação, somente um único 
comando SQL UPDATE é gerado ao final da 
transação, contendo todas as modificações. 
 
Cache de primeiro nível 
Cache de primeiro nível 
Cache de segundo nível 
• Mantém os objetos em memória e os utiliza 
mesmo entre diferentes EntityManagers de uma 
mesma EntityManagerFactory. 
 Não é usado por default, devendo ser explicitamente 
configurado para que possa ser usado. 
 Deve-se configurar que entidades vão usá-lo, ou seja, 
quais vão ficar no cache. 
 
Cache de segundo nível 
Cache de segundo nível 
• JPA 2.0 tem suporte nativo ao cache de segundo 
nível e ele é configurado através do elemento 
shared-cache-mode do persistence.xml. 
• Os modos diferentes de cache são: 
▫ ALL: automaticamente habilita todas as 
entidades; 
▫ NONE: desabilita para todas as entidades; 
Cache de segundo nível 
▫ ENABLE_SELECTIVE: habilita para todas as 
entidades que estiverem anotadas com 
@Cacheable. 
▫ DISABLE_SELECTIVE: habilita para todas as 
entidades, desabilitando somente as que estiverem 
anotadas com @Cacheable(false); 
▫ UNSPECIFIED: valor padrão assumido pelo 
shared-cache-mode. Cada implementação de JPA 
tem liberdade para definir qual modo será 
habilitado. 
Cache de segundo nível 
• As implementações mais de cache mais usadas 
são: EHCache e Infinispan. 
• Nelas podemos configurar para cada entidade o 
numero máximo de objetos que ficarão em 
memoria, e depois o que será armazenado em 
disco, etc. 
• Usaremos o módulo hibernate-ehcache. 
▫ EHCache (Easy Hibernate Cache) 
 Rápido, leve, fácil de usar. 
 Suporta cache read_only e read_write. 
 Suporta cache em memória e disco. 
Cache de segundo nível 
<persistence ...> 
 <persistence-unit name="default" 
 transaction-type="RESOURCE_LOCAL"><shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode> 
 <properties> 
 <property name="hibernate.cache.region.factory_class" 
 value= 
 "org.hibernate.cache.ehcache.EhCacheRegionFactory"/> 
 ... 
 </properties> 
 </persistence-unit> 
</persistence> 
@Entity @Cacheable 
public class Marca { 
... 
} 
Cache de segundo nível 
• Recupera objetos de qualquer entidade, desde 
que baseados na chave primária. 
Cache de consultas 
• Quando não buscamos pela chave precisamos de 
um cache diferente: o cache de consultas. 
• Não faz parte da JPA. 
• É um recurso específico do Hibernate. 
• Só funciona se o cache de segundo nível estiver 
ativado. 
• Somente será possível guardar no cache consultas 
que retornem objetos que estão com o cache 
habilitado com a anotacao @Cacheable. 
• Além disso, precisamos habilitar o cache em cada 
consulta que realizarmos. 
Cache de consultas 
... 
<persistence-unit name="default" transaction-type="RESOURCE_LOCAL"> 
 <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode> 
 <properties> 
 ... 
 <property name="hibernate.cache.use_query_cache" 
 value="true" /> 
 </properties> 
</persistence-unit> 
... 
Cache de consultas 
@NamedQuery(name=Automovel.LISTAR_DESTAQUES, 
 query="select a from Automovel a", 
 hints={ 
 @QueryHint(name="org.hibernate.cacheable", value="true"), 
 @QueryHint(name="org.hibernate.cacheRegion", 
 value=Automovel.LISTAR_DESTAQUES)}) 
@Entity 
@Cacheable 
public class Automovel { 
public static final String LISTAR_DESTAQUES = 
"Automovel.buscarDestaques"; 
... 
} 
Cache de consultas 
Query query = JpaUtil.getEntityManager() 
 .createQuery("select a from Automovel a", 
 Automovel.class); 
query.setHint("org.hibernate.cacheable", true); 
query.setHint("org.hibernate.cacheRegion", 
 Automovel.LISTAR_DESTAQUES); 
List<Automovel> automoveis = query.getResultList(); 
Cache de consultas 
... 
public class JpaUtil { 
... 
 public static Query enableCache(Query query, String region) { 
 query.setHint("org.hibernate.cacheable", true); 
 query.setHint("org.hibernate.cacheRegion", region); 
 return query; 
 } 
} 
Query query = JpaUtil.getEntityManager() 
 .createQuery("select a from Automovel a", Automovel.class); 
JpaUtil.enableCache(query, Automovel.LISTAR_DESTAQUES); 
List<Automovel> automoveis = query.getResultList(); 
Invalidando o cache de consultas 
public class JpaUtil { 
 ... 
 public static void evictCache(EntityManager em, String region){ 
 try { 
 Session session = (Session) em.getDelegate(); 
 Cache cache = session.getSessionFactory().getCache(); 
 cache.evictQueryRegion(region); 
 } 
 catch(Exception e) { 
 // provavelmente a implementação não é o Hibernate 
 } 
 } 
} 
Invalidando o cache de consultas 
@ManagedBean @ViewScoped 
public class AutomovelBean { 
 
 public String salvar(Automovel auto) { 
 EntityManager em = JpaUtil.getEntityManager(); 
 em.persist(auto); 
 JpaUtil.evictCache(em, Automovel.LISTAR_DESTAQUES); 
 return "listar"; 
 } 
 
} 
Callbacks 
• JPA permite métodos de callback para acessar o 
EntityManager. 
• Eventos disponíveis: 
▫ PostLoad 
▫ PrePersist 
▫ PostPersist 
▫ PreRemove 
▫ PostRemove 
▫ PreUpdate 
▫ PostUpdate 
Método de Callback 
@PrePersist 
void validateCreate() { 
 if (idade > 130) { 
 throw new IllegalStateException(); 
 } 
} 
Método Callback em classe Listener 
@Entity 
@EntityListeners(br.ufc.Monitor.class) 
public class Pessoa { 
 ... 
} 
public class Monitor { 
 @PostPersist 
 public void alertaNovaPessoa(Pessoa p) 
{ 
 emailRH(p); 
 } 
} 
Open Entity Manager in View 
• Uma questão comum em aplicações Web na camada de visão 
é o acesso a associações Lazy de objetos desconectados do 
EntityManager. 
• Uma solução simples é deixar o EntityManager aberto 
mesmo na camada de apresentação e só fechá-lo após o 
processamento completo da requisição. 
• O padrão “Open Entity Manager in View” faz isso. 
• Usamos um interceptador que filtra a requisição. 
• Nele podemos usar qualquer código antes e após a 
requisição. 
• O fluxo de processamento da requisição fica assim: 
▫ Início da Requisição → Filtro → Servlet/Action → Filtro → 
Fim da Requisição. 
Open Entity Manager in View 
• Para que o filtro funcione no container web, é 
necessário defini-lo no arquivo web.xml ou 
através de anotação: 
<filter> 
 <filter-name>JPAFilter</filter-name> 
 <filter-class>br.ufc.web.EntityManagerFilter</filter-class> 
</filter> 
 
<filter-mapping> 
 <filter-name>JPAFilter</filter-name> 
 <url-pattern>/*</url-pattern> 
</filter-mapping> 
Controle de Transações no Filtro 
import java.io.IOException; 
import javax.servlet.*; 
 
@WebFilter("/*") 
public class EntityManagerFilter implements Filter { 
 public void doFilter(ServletRequest request, ServletResponse response, 
 FilterChain chain) throws IOException, ServletException { 
 try { 
 JPAUtil.beginTransaction(); 
 chain.doFilter(request, response); 
 JPAUtil.commit(); 
 } catch (Throwable e) { 
 System.out.println(e.getMessage() + "\n" + e.getCause()); 
 e.printStackTrace(); 
 JPAUtil.rollback(); 
 throw new ServletException(e); 
 } finally { 
 JPAUtil.closeEntityManager(); 
 } 
 } 
 
 public void destroy() {} 
 public void init(FilterConfig arg0) throws ServletException {} 
} 
Referências 
• CORDEIRO, Gilliard. Aplicações Java para web com JSF e JPA. Casa do Código. 
• Apostila da K19: K22 - Desenvolvimento Web com JSF 2 e JPA 2 
▫ http://www.k19.com.br/downloads/apostilas/java/k19-k12-desenvolvimento-web-com-jsf2-e-jpa2 
• Apostila da K19: K22 - Persistência com JPA2 e Hibernate 
▫ http://www.k19.com.br/downloads/apostilas/java/k19-k21-persistencia-com-jpa2-e-hibernate 
• Hibernate EntityManager 
▫ http://docs.jboss.org/hibernate/orm/4.0/hem/en-US/html/ 
• Dynamic, typesafe queries in JPA 2.0 
▫ How the Criteria API builds dynamic queries and reduces run-time failures 
▫ http://www.ibm.com/developerworks/java/library/j-typesafejpa/ 
• Apresentação – JPA: Persistência padronizada em Java – Flávio Henrique Curte 
▫ http://www.javanoroeste.com.br/tech_days_votuporanga/palestras/Java_Persistence_
API.pdf 
• Screencast da Caelum – Primeiros Passos para JPA – Fábio Kung 
▫ http://blog.caelum.com.br/2007/05/15/screencast-primeiros-passos-para-a-jpa/ 
• Resumo de JPA – Quick Ref Card 
▫ http://www.solarmetric.com/resources/ejb-api-quickref.pdf 
• Exemplo de JPA – Java Persistence Example 
▫ https://glassfish.dev.java.net/javaee5/persistence/persistence-example.html 
Referências 
• Os 7 hábitos dos desenvolvedores Hibernate e JPA 
altamente eficazes (por Paulo Silveira da Caelum) 
▫ http://blog.caelum.com.br/os-7-habitos-dos-
desenvolvedores-hibernate-e-jpa-altamente-eficazes/ 
• JPA Annotation Reference 
▫ http://www.oracle.com/technology/products/ias/topl
ink/jpa/resources/toplink-jpa-annotations.html 
• JPA Inheritance Strategies 
▫ http://www.jpox.org/docs/1_2/jpa_orm/inheritance.
html 
 
 
Referências 
• Open Session in View (Hibernate) 
▫ http://www.hibernate.org/43.html 
• EJB 3.0 Persistence API – Quick Reference Guide 
▫ http://www.solarmetric.com/resources/ejb-api-
quickref.pdf 
• Hibernate Avançado 
▫ Paulo Silveira e Guilherme Moreira 
▫ Revista Mundo Java – Nº 19 
• Gerenciando aSessão do Hibernate em Aplicações WEB 
▫ Nico Steppat e Guilherme Moreira 
▫ Revista Mundo Java – Nº 25 
 
Referências - Recursos 
• Hibernate 
▫ http://www.hibernate.org/ 
• Introduction to Hibernate Caching 
▫ http://www.javabeat.net/articles/37-
introduction-to-hibernate-caching-1.html 
• Hibernate Caching 
▫ http://www.javapassion.com/j2ee/hibernatecachi
ng.pdf 
Referências – Livros 
• CORDEIRO, Gilliard. Aplicações Java para web 
com JSF e JPA. Casa do Código. 
• Pro EJB 3: Java Persistence API (Pro) – Mike 
Keith e Merrick Schincariol. 2006. 
• EJB 3 in Action – Debu Panda, Reza Rahman e 
Derek Lane. 2007. 
• Beginning EJB 3 Application Development: 
From Novice to Professional – Raghu R. Kodali, 
Jonathan R. Wetherbee e Peter Zadrozny. 2006. 
• Java Persistence with Hibernate – Christian 
Bauer e Gavin King 
▫ Capítulo 2: http://www.manning.com/bauer2/ 
Referências – Revistas 
• Revista Java Magazine 
▫ Ed. 25 – Persistência Turbinada I: Como usar o JDBC de modo 
eficiente para criar classes DAO – Osvaldo Pinali Doederlein 
▫ Ed. 26 – Persistência Turbinada II: Recursos avançados do JDBC 
– Osvaldo Pinali Doederlein 
▫ Ed. 39 – Java EE 5: Um Enterprise Edition muito mais fácil – 
Osvaldo Pinali Doederlein 
▫ Ed. 39 – Persistência no Java EE 5: Iniciando com a Java 
Persistence API – André Dantas Rocha e Sérgio Oliveira Kubota 
▫ Ed. 41 – Java EE 5 na Prática: Criando uma aplicação passo a 
passo com EJB 3.0, JPA e NetBeans 5.5 – Osvaldo Pinali 
Doederlein 
▫ Ed. 42 – Dados e Mapeamento: Explorando técnicas e tecnologias 
para persistência de dados – Osvaldo Pinali Doederlein

Continue navegando