SlideShare uma empresa Scribd logo
1 de 195
Baixar para ler offline
JAVAEE7
JPA
javapersistenceapi
Helder da Rocha (helder@acm.org)
Atualizado em setembro de 2016
JAVAEE7 Sobre este tutorial
Este é um tutorial sobre tecnologia JPA (de acordo com a especificação Java EE 7) criado
para cursos presenciais e práticos de programação por Helder da Rocha.
Este curso aborda os conhecimentos essenciais para usar JPA na prática usando Hibernate
ou EclipseLink como provedor (consulte a documentação oficial para detalhes).
Este material poderá ser usado de acordo com os termos da licença Creative Commons BY-
SA (Attribution-ShareAlike) descrita em http://creativecommons.org/licenses/by-sa/3.0/br/
legalcode.
O código dos exemplos está disponível em repositório público no GitHub e é software livre
sob os termos da licença Apache 2.0.
JAVAEE7 Conteúdo
1. Introdução
2. Configuração do ambiente
3. Persistência
4. Mapeamento de entidades
5. Mapeamento de relacionamentos
6. Mapeamento de herança
7. Queries JPQL
8. Queries Criteria
9.Tuning: transações, cache e locks
JAVAEE7
JPA
javapersistenceapi
1
introdução
JAVAEE7 O que é JPA?
•Java Persistence API: especificação Java EE que define um mapeamento
entre uma estrutura relacional e um modelo de objetos em Java
•Pode ser também usado de forma standalone, em aplicações Java SE,
utilizando um provedor de persistência independente
•Java EE 7 adota a especificação JPA 2.1 (JSR 338).
•JPA permite a criação de entidades persistentes - objetos gerenciados
que retém seu estado além do tempo em que estão na memória
•Oferece uma camada de persistência (CRUD de objetos) e um
mecanismo de mapeamento objeto-relacional (ORM) declarativo.
JAVAEE7 Object-Relational Mapping (ORM)
•Tempo de configuração
• Classes mapeadas a tabelas (esquemas)
•Tempo de execução
• Instâncias (objetos) automaticamente sincronizadas com registros
conta correntista saldo
1 Gargantua 1370
2 Pantagruel 3450
3 Gargamel 800
4 Morticia 8200
Classe Conta
String codigo
String nome
double saldo
instância:Conta
codigo="4"
nome="Morticia"
saldo=8200
Tabela Conta
Banco de Dados Relacional
JAVAEE7 Camada de persistência
•JPA oferece uma API para interagir com objetos persistentes
mapeados através de ORM
•AAPI é proporcionada pela interface EntityManager e contém
•Métodos para gravar objetos em meio persistente (persist), remover
(remove) e atualizar (update)
•Métodos para construir e processar consultas usando scripts (JPA
Query Language) ou objetos (Criteria)
•Métodos para configurar o comportamento do cache de objetos
(que cuida da sincronização do estado de objetos e transações)
JAVAEE7 Configuração de JPA
•Para configurar JPA em uma aplicação é necessário que essa aplicação
tenha acesso, através do seu Classpath, aos seguintes componentes:
•Módulo contendo a API do JPA (as classes, interfaces, métodos,
anotações do pacote javax.persistence)
•Um provedor de persistência JPA (ex: Hibernate, EclipseLink) que
implementa as interfaces da API
•Drivers necessários para configuração do acesso aos datasources usados
(e pools de conexão, se houver)
•Um arquivo persistence.xml para configurar a camada de persistência.
JAVAEE7 Unidade de persistência
•O contexto de persistência, usado para sincronizar as instâncias
persistentes com o banco de dados é chamado de Entity Manager
•Controla o ciclo de vida das instâncias
•Pode ser instanciado pela própria aplicação (em aplicações standalone),
obtido via JNDI ou injeção de dependências (padrão em Java EE)
•O conjunto de entity managers e as entidades que eles gerenciam
configura uma unidade de persistência (Persistence Unit).
•Declarada no arquivo persistence.xml
•Referenciada em classes que usam objetos persistentes (DAOs, fachadas,
beans, servlets)
JAVAEE7 persistence.xml mínimo
•Deve estar no Classpath acessível pelas classes Java usadas na aplicação em 

/META-INF/persistence.xml, e possui a seguinte configuração mínima:
•Este exemplo é utilizável em servidor Java EE que tenha sido configurado
para oferecer um datasource default (java:comp/DefaultDataSource).
•Normalmente aplicações usam datasources selecionadas de forma explícita.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" 

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence 

http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="MyPU" transaction-type="JTA">
</persistence-unit>
</persistence>
JAVAEE7 DataSource com JTA
•Este persistence.xml típico de uma aplicação JPA simples rodando em
um servidor Java EE 7 declara o nome da unidade de persistência e:
•o modelo de transações utilizada (JTA – gerenciada pelo container),
•o nome JNDI de um datasource específico (previamente configurado)
•uma única entidade mapeada
•uma única propriedade de configuração específica do provedor usado
<persistence version="2.1" …>
<persistence-unit name="com.empresa.biblioteca.PU" transaction-type="JTA">
<jta-data-source>jdbc/Biblioteca</jta-data-source>
<class>br.empresa.biblioteca.entity.Livro</class>
<properties>
<property name="eclipselink.deploy-on-startup" value="true" />
</properties>
</persistence-unit>
</persistence>
Os detalhes de conexão com o banco de dados
precisam ser configurados no servidor de aplicações
JAVAEE7 EclipseLink e PostgreSQL
•Exemplo de persistence.xml usado para acessar mesmos dados via
camada de persistência configurada localmente (transações gerenciadas
pela aplicação), usando provedor EclipseLink e banco PostgreSQL
<persistence version="2.1" … >
<persistence-unit name="com.empresa.biblioteca.PU"
transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>br.empresa.biblioteca.entity.Livro</class>
<properties>
<property name="javax.persistence.jdbc.driver" 

value="org.postgresql.Driver" />
<property name="javax.persistence.jdbc.url" 

value="jdbc:postgresql://localhost:5432/postgres" />
<property name="javax.persistence.jdbc.user" value="postgres" />
<property name="javax.persistence.jdbc.password" value="admin" />
</properties>
</persistence-unit>
</persistence>
JAVAEE7 Hibernate e MySQL
•Este persistence.xml configura unidade de persistência com transações locais
e provedor Hibernate acessando localmente um banco de dados MySQL
<persistence … >

<persistence-unit name="LojaVirtual" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>lojavirtual.Produto</class>
<properties>
<property name="hibernate.dialect"
value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.connection.driver_class"
value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.connection.url"
value="jdbc:mysql://localhost:3306/test"/>
</properties>
</persistence-unit>
</persistence>
JAVAEE7 Entidades e mapeamento
•A arquitetura do JPA baseia-se no mapeamento de tabelas a classes,
colunas a atributos

•O objetivo do mapeamento é construir uma hierarquia de entidades
•Entidade (Entity) é um objeto persistente. Em JPA é um JavaBean
(POJO) mapeado a uma tabela
•Uma entidade JPA pode ser mapeada a uma tabela de duas formas:
•Através de elementos XML no arquivo orm.xml
•Através de anotações em classes, métodos, atributos, construtores
JAVAEE7 Mapeamento em orm.xml
•Os únicos tags obrigatórios são <entity> e <id>, e os atributos name.
Pode-se ter mais detalhamento (ex: tipos, constraints) ou menos (ex:
omitir tags com nomes de tabela e colunas, se forem iguais).
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" 

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm 

http://xmlns.jcp.org/xml/ns/persistence/orm/orm_2_1.xsd" version="2.1">
<entity name="Livro" class="br.com.argonavis.Livro" access="FIELD">
<table name="LIVRO"/>
<attributes>
<id name="id">
<column name="ID"/>
<generated-value strategy="TABLE" generator="LIVRO_SEQ"/>
</id>
<basic name="titulo"> <column name="TITULO"/> </basic>
<basic name="paginas"> <column name="PAGINAS"/> </basic>
</attributes>
</entity>
</entity-mappings> Se existir, deve estar localizado em META-INF/orm.xml
JAVAEE7 Mapeamento com anotações
•Para declarar uma entidade com anotações JPA é necessário no mínimo
anotar a classe com @Entity e anotar pelo menos um atributo (ou método)
com @Id, indicando sua chave primária
•Atributos expostos via getters/setters são mapeados por default a colunas
de mesmo nome
@Entity public class Livro implements Serializable {
@Id private Long id;
private String titulo;
private int paginas;
public Long getId() { return id;}
public void setId(Long id) { this.id = id;}
public String getTitulo() { return this.titulo;}
public void setTitulo(String titulo) { this.titulo = titulo;}
public int getPaginas() { return this.paginas;}
public void setPaginas(int paginas) { this.paginas = paginas;}
}
É preciso também determinar como o Id será
atribuído (se gerado pelo banco ou fornecido)
JAVAEE7 Mapeamento com anotações
•Pode-se mudar os defaults e realizar configurações adicionais é
usando anotações como @Table, @Column, @CollectionTable,
@JoinTable, @JoinColumn, etc.
@Entity @Table(name="BOOK")
public class Livro implements Serializable {
@Id
private Long id;
@Column(name="TITLE")
private String titulo;
@Column(name="PAGES")
private int paginas;
…
}
JAVAEE7 Exercícios: configuração
•Configuração do ambiente para realizar os exercícios
•Pode ser necessário adaptar os exercícios ao ambiente usado (banco de
dados, provedor de persistência, IDE, ambiente Java EE ou standalone,
duração do treinamento)
•Alguns exercícios usam arquivos disponíveis no repositório GitHub
•Scripts SQL 99 e aplicações JDBC em Java podem ser usados para criar
tabelas usadas em exercícios (é necessário configurá-los)
•As hierarquias de classes e diagramas de entidades a seguir poderão ser
usados nos exercícios (que irão fazer referência a eles)
JAVAEE7 Exercícios: Hierarquia e SQL 1
CREATE TABLE Livro(
id INTEGER PRIMARY KEY,
isbn VARCHAR(13) UNIQUE,
titulo VARCHAR(256),
idioma CHAR(2)
)
Livro
id: int
titulo: String
isbn: String
idioma: String
JAVAEE7 Exercícios: Hierarquia e SQL 2
Movie
id: int
title: String
imdb: String
director: Director
year: int
duration: int
Director
id: int
name: String
CREATE TABLE Diretor (
id INTEGER PRIMARY KEY,
nome VARCHAR(256),
)
CREATE TABLE Filme (
id INTEGER PRIMARY KEY,
imdb CHAR(9) NOT NULL,
titulo VARCHAR(256),
diretor INTEGER,
ano INTEGER,
duracao INTEGER,
constraint fk_diretor
foreign key (diretor)
references Diretor(id)
)
*
JAVAEE7 Exercícios: Hierarquia 3
1
1..*
1
1
*
PK
FK
Cliente
nome
email
pedidos
cartao
Usuario
id
senha
userid
Produto
id
nome
preco
Pedido
id
cliente
status
Item
id
pedido
produto
quantidade
Operador
codigo
versao
JAVAEE7 Exercícios: SQL 1
create table produtos (
produto_id integer primary key,
nome_prod varchar(64),
preco numeric(10,2),
);
create table usuarios (
usuario_id varchar(8) primary key,
senha varchar(16),
userid varchar(16)
);
create table clientes (
cliente_id varchar(8) primary key,
nome varchar(512),
email varchar(256),
usuario_fk integer,
cartao varchar(16),
constraint fk_usuario foreign key (usuario_fk)
references usuarios(usuario_id)
);
JAVAEE7 Exercícios: SQL 2
create table operadores (
operador_id varchar(8) primary key,
codigo varchar(8),
versao integer,
usuario_fk integer,
constraint fk_usuario foreign key (usuario_fk)
references usuarios(usuario_id)
);
create table pedidos (
pedido_id integer primary key,
cliente_fk integer,
status varchar(16),
constraint fk_cliente foreign key (cliente_fk)
references clientes(cliente_id)
);
create table itens (
item_id integer primary key,
pedido_fk integer,
produto_fk integer,
qte integer,
constraint fk_pedido foreign key (pedido_fk)
references pedidos(pedido_id),
constraint fk_produto foreign key (produto_fk)
references produtos(produto_id)
);
JAVAEE7 Exercícios: Hierarquia 4
Corrida
Etapa
Participante Ingressoingresso
participante
Localidade
participantes
etapas
origem
destino
valor
status
nome
nome
nome
nome
*
*
1
1
1
*
etapas
1
1
JAVAEE7 Exercícios:

Hierarquia 5
Livro
id: int
titulo: String
isbn: String
idioma: String
Autor
id: int
nome: String
Editora
id: int
nome: String
Assunto
id: AssuntoPK
descricao: String
Exemplar
id: int
disponivel: boolean
ExemplarEletronico
id: int
tamanho: long
ExemplarImpresso
id: int
paginas: int
Usuario
id: int
nome: String
emprestimos
usuario
livro
assunto
editora
autores
obras
titulos
contexto
assuntos 10
0..1
*
1
*
*
1
*
1
*
1
*
JAVAEE7
JPA
javapersistenceapi
2
configuraçãodoambiente
JAVAEE7 Configuração standalone
•Usada em projetos Java EE para rodar testes de integração com o banco ou em
aplicações JPA standalone
•É preciso incluir explicitamente no Classpath os JARs da API, do provedor JPA e
driver do banco de dados (e pool de conexões se houver)
<dependencies>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4.1208</version>
<scope>runtime</scope>
</dependency>
</dependencies>
Configuração das
dependências Maven para
para acesso JPA usando
EclipseLink 2.5 e banco de
dados PostgreSQL
JAVAEE7 Configuração standalone
•Como as transações serão controladas pela aplicação e serão locais, a unidade
de persistência declara o tipo de transações como RESOURCE_LOCAL:
<persistence version="2.1"…>
<persistence-unit name="tutorial-jpa"
transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>br.com.argonavis.javaee7.jpa.intro.Livro</class>
<properties>
…
<property name="eclipselink.ddl-generation" 

value="drop-and-create-tables" />
</properties>
</persistence-unit>
</persistence>
Entidade a ser
configurada
Configuração do EclipseLink para gerar
tabelas automaticamente
(o Hibernate suporta uma equivalente)
JAVAEE7 Criação do EntityManager (standalone)
•A fábrica que cria o EntityManager pode ser obtida via consulta JNDI
global a um servidor (se houver container cliente configurado), ou criada
localmente com um objeto Persistence.
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class LivroTest {
@Test
public void testPersist() throws Exception {
EntityManagerFactory factory = 

Persistence.createEntityManagerFactory("tutorial-jpa");
EntityManager em = factory.createEntityManager();
...
em.close();
}
}
Criação local do
EntityManager
Configuração para usar a
unidade de persistência
declarada no persistence.xml
JAVAEE7 Criação da entidade
•A entidade a ser sincronizada com a tabela é instanciada e
configurada normalmente em Java puro
public class LivroTest {
@Test
public void testPersist() throws Exception {
...
Livro livro = new Livro();
livro.setTitulo("Meu Livro");
livro.setPaginas(100);
...
}
}
JAVAEE7 Uso da persistência (standalone)
•Padrão básico: obter o contexto de persistência (createEntityManager)
seguido do contexto transacional (begin), realizar as operações envolvendo
persistência, e fechar o contexto transacional (commit se sucesso ou rollback
se falha, fechando o contexto de persistência (close) no final da operação.
public class LivroTest {
@Test
public void testPersist() throws Exception {
...
try {
em.getTransaction().begin();
em.persist(livro); // cria um registro novo no commit()
em.getTransaction().commit();
} catch (Exception e) {
em.getTransaction().rollback();
} finally {
em.close();
}
}
} // detalhes do teste (asserts) omitidos
É preciso obter o
contexto transacional
do EntityManager:
persist() precisa ser
chamada dentro de um
contexto transacional
JAVAEE7 Configuração em Java EE
•Em Java EE o suporte a JPA é nativo, e o acesso ao banco de dados
deve ocorrer através de um datasource previamente configurado
no servidor, acessível dentro de um contexto JTA
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
...
</dependencies>
Dependências em um projeto
Maven não são incluídas no
componente (JAR): o driver do
banco, pool e provedor JPA
fazem parte do servidor
JAVAEE7 Configuração em Java EE
•O arquivo persistence.xml declara estratégia transacional JTA
(gerenciada pelo container) e em vez de dados para acesso ao
banco, informa o caminho JNDI para o datasource correspondente
<persistence version="2.1" …>
<persistence-unit name="tutorial-jpa" transaction-type="JTA">
<jta-data-source>jdbc/TutorialJPA</jta-data-source>
<class>br.com.argonavis.javaee7.jpa.intro.ejb.Livro</class>
</persistence-unit>
</persistence>
JAVAEE7 Acesso via WebServlet
•Em Java EE o EntityManager poderá ser obtido via JNDI injeção de dependências
com de @PersistenceContext (ou via CDI, se previamente configurado)
@WebServlet("/Livro") public class LivroTestServlet extends HttpServlet {
@PersistenceContext(unitName="tutorial-jpa")

EntityManager em;
@Resource 

UserTransaction ut;
protected void doGet(HttpServletRequest rq, HttpServletResponse rs) 

throws ServletException, IOException {
Writer out = rs.getWriter();
try {
ut.begin();
List<Livro> livros =
em.createQuery("select livro from Livro livro").getResultList();
for(Livro livro : livros)
out.write("<p>"+livro.getTitulo()+ "</p>");
ut.commit();
} catch (…) {…} // rollback e finalização
}
UserTransaction é necessário para
delimitar o contexto transacional
JAVAEE7
@Stateless

public class LivroDAOSessionBean {
@PersistenceContext

EntityManager em;
public Livro findByID(Long id) {
Query query = em.createNamedQuery("selectById");
query.setParameter("id", id);
return (Livro)query.getSingleResult();
}
public List<Livro> findAll() {
return (List<Livro>)em.createNamedQuery("selectAll")

.getResultList();
}
public void delete(Livro livro) { em.remove(livro); }
public void update(Livro livro) { em.merge(livro); }
public Livro insert(Livro livro) { return em.merge(livro); }
}
Acesso via EJB
Se houver apenas uma unidade
de persistência, o nome dela não
precisa ser informado
Os métodos de um Session Bean são
transacionais por default. Haverá
rollback se houver exceção
JAVAEE7 Named queries
•Um @NamedQuery contém JPQL associado a um nome que
pode ser usado pelos clientes para obter referência a um query:
•Exemplo:
@Entity
@NamedQueries({
@NamedQuery(name="selectAll",
query="SELECT livro FROM Livro livro"),
@NamedQuery(name="selectById",
query="SELECT livro FROM Livro livro WHERE livro.id=:id")
})
public class Livro { ... }
TypedQuery<Livro> query = 

em.createNamedQuery("selectById", Livro.class);
JAVAEE7 Acesso via CDI
•Métodos não são transacionais por default. O contexto transacional pode
ser obtido de duas formas:
•UserTransaction (como no WebServlet)
•Anotação @Transactional (comportamento igual ao EJB)
@Named public class LivroDAOManagedBean {
@Inject EntityManager em;
public Livro findByID(Long id) {
TypedQuery<Livro> query = 

em.createNamedQuery("selectById", Livro.class);
query.setParameter("id", id);
return query.getSingleResult();
}
public List<Livro> findAll() {
return em.createNamedQuery("selectAll", Livro.class)

.getResultList();
}
@Transactional public void delete(Livro livro) { em.remove(livro); }
@Transactional public void update(Livro livro) { em.merge(livro); }
@Transactional public Livro insert(Livro livro) { return em.merge(livro); }
}
JAVAEE7 Passo-a-passo JPA: configuração
•Crie um projeto (Maven, Eclipse, NetBeans, etc)
•Configure dependências necessárias para compilar JPA (e executar se standalone)
•Configure um banco de dados no seu projeto (se standalone) ou no servidor de
aplicações (se Java EE) e use as propriedades para configurar o persistence.xml
•Inclua dados de configuração em META-INF/persistence.xml definindo um nome para
a unidade de persistência, e tipo RESOURCE_LOCAL, se standalone, e JTA, se Java EE
<persistence version="2.1" ... >
<persistence-unit name="biblioteca-PU" transaction-type="JTA">
<jta-data-source>jdbc/sample</jta-data-source>
<class>biblioteca.Livro</class>
<properties>
<property name="javax.persistence.schema-generation.database.action"

value="drop-and-create"/>
</properties>
</persistence-unit>
</persistence>
Use para gerar as tabelas
automaticamente
Entidade mapeada
JAVAEE7 Passo-a-passo JPA: mapeamento
•Crie um POJO (classe Java com atributos privativos acessíveis via getters e setters)
•Declare @Entity, @Id e uma estratégia de geração do ID (depende do banco de dados)
•Inclua uma referência à entidade no persistence.xml (veja slide anterior)
@Entity
public class Livro {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String titulo;
private String isbn;
private String idioma;
public int getId() {return id;}
public void setId(int id) {this.id = id;}
public String getTitulo() {return titulo;}
...
}
Gera ID automaticamente
(depende do banco usado)
JAVAEE7 Passo-a-passo JPA: persistência
•Crie um cliente Java. Em Java EE use um WebServlet, ManagedBean
(exemplo abaixo) ou Session Bean
•Obtenha uma referência para o EntityManager da unidade de persistência
•Chame os métodos de EntityManager dentro de contexto transacional
(automático em Session Beans)
@Named @RequestScoped
public class LivroBean {
@PersistenceContext(unitName="biblioteca-PU")
EntityManager em;
@Override @Transactional
public Collection<Livro> getLivros() {
String query = "select livro from Livro livro";
return em.createQuery(query, Livro.class).getResultList();
}
@Override @Transactional
public int insert(Livro livro) {
em.persist(livro);
return em.merge(livro).getId();
} ...
<h:dataTable value="#{livroBean.livros}" 

var="livro">
<h:column>#{livro.isbn}</h:column>
<h:column>#{livro.titulo}</h:column>
<h:column>#{livro.idioma}</h:column>
Cliente para o
ManagedBean
JAVAEE7 Exercícios
•1. Configure seu ambiente para usar JPA (persistence.xml)
•a.Ambiente standalone: carregue as dependências necessárias no ClassPath,
configure um banco de dados e um provedor
•b.Ambiente Java EE: configure um datasource JTA no servidor de aplicações e um
provedor de persistência
•2. Construa a entidade da Hierarquia 1 (classe Livro)
•Não crie uma tabela em SQL: configure para que as tabelas do banco sejam geradas
automaticamente) e chame métodos para inserir e selecionar objetos
•Depois de configurado, rode a classe PopulateLivros para preencher a tabela com
dados que possam ser pesquisados
JAVAEE7
JPA
javapersistenceapi
3
persistência
JAVAEE7 Operações CRUD
•Create, Retrieve, Update, Delete (Criar, Recuperar,Atualizar,
Remover) são as principais tarefas da camada de persistência
•Podem envolver uma entidade ou uma rede de entidades
interligadas através de relacionamentos
•JPA oferece várias maneiras de realizar operações CRUD:
•Métodos de persistência transitiva: persist, merge, delete, find
•Java Persistence Query Language (JPQL)
•API Criteria
•SQL nativo
JAVAEE7 Retrieve com JPQL
•A obtenção de uma entidade, o “R” de “Retrieve” do acrônimo CRUD,
pode ser feita conhecendo-se sua chave primária através de find:
Livro livro = em.find(Livro.class, 1234);
•Outra alternativa é realizar uma consulta pesquisando o estado da
entidade com JPQL através de um Query (ou TypedQuery):
TypedQuery query = 

em.createQuery("select m from Livro m where m.id=:id",
Livro.class);
query.setParameter("id", 1234);
Livro livro = query.getSingleResult();
JAVAEE7 Retrieve com Criteria
•Criteria é um query construído dinamicamente via relacionamentos entre
objetos. É ideal para pesquisas que são construídas em tempo de execução:
•Para usar a API desta forma, a classe Livro_class foi gerada automaticamente
(veja: Criteria Metamodel API) pelas ferramentas da IDE (plug-in Maven)
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Livro> criteria = builder.createQuery(Livro.class);
Root<Livro> queryRoot = criteria.from(Livro.class);
criteria.where(builder.equal(queryRoot.get(Livro_.id), 1234));
TypedQuery<Livro> q = em.createQuery(criteria);
Livro livro = q.getSingleResult();
JAVAEE7 Create-Update-Delete com find e JPQL
•Operações que envolvem atualização, “Create”, “Update” e “Delete”,
geralmente são executadas através de métodos de persistência
transitiva persist, merge e delete
•A mesma alteração também pode ser realizada via JPQL:
Query query = em.createQuery("UPDATE Livro m"
+ "SET m.titulo = :titulo WHERE m.id = :id");
query.setParameter("titulo", "Novo título");
query.setParameter("id", "1234");
query.executeUpdate();
Livro livro = em.find(Livro.class, 1234);
livro.setTitulo("Novo título");
em.merge(livro);
JAVAEE7 Create-Update-Delete com Criteria
•As mesmas operações podem ser realizadas com a API Criteria
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaUpdate updateCriteria =

builder.createCriteriaUpdate(Livro.class);
Root<Livro> updateRoot = 

updateCriteria.from(Livro.class);
updateCriteria.where(builder.equal(updateRoot.get(Livro_.id), 

"1234"));
updateCriteria.set(updateRoot.get(Livro_.titulo), 

"Novo título");
Query q = em.createQuery(updateCriteria);
q.executeUpdate();
JAVAEE7 Operações de persistência
•Uma entidade pode estar em quatro estados durante seu ciclo de vida
•transiente (new) - @Id = null
•persistente (managed) - @Id != null e sincronizado com tabela
•desligado (detached) - @Id != null e não sincronizado (pode estar obsoleto)
•removido (removed) - @Id != null mas registro inexistente na tabela
•O estado determina o comportamento do objeto quando são chamadas
operações de persistência transitiva sobre ele
•Entidade nova (transiente) ainda não inserida no banco tem ID null
•Quando a entidade torna-se persistente ela recebe um ID. Uma vez
atribuído um ID a uma entidade, esse valor não muda mais
JAVAEE7 Ciclo de vida e operações de persistência
JAVAEE7 Controle da persistência
•void persist(objeto) – Gera SQL INSERT e transforma o objeto em uma entidade
persistente. Causa EntityExistsException se o ID já existir no banco.
•Object merge(objeto) – Gera SQL UPDATE ou INSERT e devolve a entidade construída. O
INSERT será gerado se o ID do objeto for null. Caso contrário, o ID será chave primária para
realizar UPDATE. Causa IllegalArgumentException se ID não for null e não existir no banco.
•void remove(objeto) – Remove o registro do banco, desligando a entidade
permanentemente.
•void detach(objeto) – Separa a instancia do seu registro tornando a entidade desligada
(detached). Ocorre em entidades usadas fora do contexto transacional. Um merge() ou
refresh() dentro do contexto transacional religa a entidade tornando-a persistente.
•void refresh(objeto) – Sincroniza a entidade com dados obtidos do banco, sobrepondo
alterações que tenham sido feitas no estado do objeto.
•void flush() – Sincroniza as entidades do contexto de persistência (oposto de refresh).
JAVAEE7 Estados da
Persistência
Transiente
Desligado
Persistente
Pessoa
nome	=	Yoda
id	=	0
Pessoa
id nome
Pessoa
nome	=	Yoda
id	=	1
Pessoa
id nome
1 Yoda
Pessoa
nome	=	Jabba
id	=	1
Pessoa
id nome
1 Jabba
Pessoa
nome	=	Jabba
id	=	1
Pessoa
id nome
1 Jabba
Pessoa
nome	=	Luke
id	=	1
Pessoa
id nome
1 Jabba
Classes Tabelas
Atualização não foi sincronizada no banco
JAVAEE7 Callbacks
•@PostLoad - executado depois que uma entidade foi carregada no contexto
de persistência atual (ou refresh)
•@PrePersist - executado antes da operação persist ser executada (ou
cascade - sincronizado com persist se entidade for sincronizada via merge)
•@PostPersist - executado depois que entidade foi persistida (inclusive via
cascade)
•@PreUpdate - antes de operação UPDATE
•@PostUpdate - depois de operação UPDATE
•@PreRemove - antes de uma operação de remoção
JAVAEE7 EntityListener
•Para declarar callbacks em uma classe separada, pode-se usar a anotação
@EntityListener na entidade informando o nome da classe que os contém:
•Neste caso, os métodos devem receber a entidade como parâmetro:
@Entity
@EntityListeners(LivroListener.class)
public class Livro implements Serializable {
…
}
public class LivroListener {
@PostLoad
public void livroLoaded(Livro livro) { ... }
...
}
JAVAEE7 Exercícios
•3. Escreva um cliente JPA simples para
•a) Inserir uma lista de livros no banco de dados (converta o código de
PopulateLivros.java para JPA)
•b) Listar os livros
•c) Alterar um dos livros (trocar o título)
•d) Remover um dos livros
•e) Recuperar um dos livros pela chave primária
•f) Listar a coleção de objetos resultante
•4. Execute a classe PopulateFilmes.java (que cria a Hierarquia 2) e escreva
um cliente que liste todos os filmes e diretores
JAVAEE7
JPA
javapersistenceapi
4
mapeamentodeentidades
JAVAEE7 Mapeamento de entidades
•Uma classe que representa uma entidade
• deve ser anotada com @Entity (ou declarada como <entity> no
deployment descriptor orm.xml)
• deve ter um campo @Id (a menos que participe como subclasse de uma
hierarquia mapeada em JPA)
• se não usar os valores default, deve declarar mapeamentos explícitos
para tabelas e colunas (@Table, @Column, @JoinColumn)
•Deve ter um construtor sem argumentos e não pode ser interface
ou um enum ou classe final, nem ter variáveis de instância ou
métodos finais
JAVAEE7 Mapeamento de entidades
•Suportam herança, associações polimórficas, queries polimórficos
• Podem estender classes comuns e vice-versa
• Somente entidades podem ser usadas em queries JPA
•O estado persistente é representado pelas variáveis de instância
• Acessadas via propriedades (getters/setters)
• Por default, variáveis de instância não declaradas transient e que
não tenham a anotação @Transient são consideradas persistentes
JAVAEE7 Mapeamento de entidades
•Assinaturas válidas para propriedades:
• Propriedades escalares (value-types) ou lado unitário de associações com
entidades (@Column):

T getProperty() e void setProperty(T t)
• Coleções de escalares (value-types) ou lado múltiplo de associações com
entidades (@JoinColumn)

Set<T> getProperty() e void setProperty(Set<T>)
•Tipos permitidos:
• Value-types: primitivos, String, BigInteger, BigDecimal, Date, Calendar,Time,
Timestamp, byte[], Byte[], char, Character[], enums e coleções desses valores
• Tipos serializáveis e coleções de tipos serializáveis
• Entidades e coleções de entidades
JAVAEE7 Mapeamento com defaults
@Entity
public class Cliente implements Serializable {
@Id
private Long id;
private String nome;
private Endereco endereco;
@OneToMany
private Set<Pedido> pedidos = new HashSet();
@ManyToMany
private Set<Pagamento> formasPagamento = new HashSet();
public Cliente() {}
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
...
public Collection<Order> getPedidos() { return pedidos; }
public void setPedidos(Collection<Pedido> pedidos) { this.pedidos = pedidos; }
public Set<Pagamento> getFormasPagamento() { return formasPagamento; }
...
}
Usando o mínimo de anotações!
Anotações ausentes (ex: @Column, @Table,
etc.) resultam em comportamento default
(ex: tabela com mesmo nome que classe)
Anotações também possuem
propriedades configuráveis; 

se omitidas, são usadas as default
JAVAEE7 Mapeamento detalhado
@Entity @Table(name="CLIENTES", schema="loja")
public class Cliente implements Serializable {
@Id @GeneratedValue(strategy=SEQUENCE, generator="CLI_SEQ")
@Column(name="CUST_ID")
private Long id;
@Basic @Column(name="NOME_CL", nullable=false, length=512)
private String nome;
@Basic @Column(name="END_CL", nullable=false, length=512)
private Endereco endereco;
@OneToMany(Cascade={CascadeType.ALL}, mappedBy="cliente", fetch=FetchType.EAGER)
@JoinColumn(name="CLIENTE_ID", nullable=false)
private Set<Pedido> pedidos = new HashSet();
@ManyToMany(mappedBy="clientes") @OrderBy("valor ASC")
@JoinTable(name="CLIENTES_PAGAMENTOS",
joinColumns= @JoinColumn(name="CLIENTE_ID", referencedColumnName="ID"),
inverseJoinColumns= @JoinColumn(name="PAG_ID", referencedColumnName="ID"))
private Set<Pagamento> formasPagamento = new HashSet();
...
}
Anotações detalhando forma como
entidade é mapeada às tabelas, e
selecionando configurações
default para gravação e
recuperação de objetos
JAVAEE7
•5. Configure um mapeamento entre a tabela Livro e a classe Livro
•6. Configure um mapeamento entre a classe Movie e a tabela Filme
Exercícios
CREATE TABLE Livro(
id INTEGER PRIMARY KEY,
isbn VARCHAR(13) UNIQUE,
titulo VARCHAR(256),
idioma CHAR(2)
)
CREATE TABLE Filme (
id INTEGER PRIMARY KEY,
imdb CHAR(9) NOT NULL,
titulo VARCHAR(256),
diretor VARCHAR(64),
ano INTEGER,
duracao INTEGER
)
Livro
id: int
titulo: String
isbn: String
idioma: String
Movie
id: int
title: String
imdb: String
director: Director
year: int
duration: int
JAVAEE7
JPA
javapersistenceapi
5
mapeamentoderelacionamentos
JAVAEE7 Relacionamentos entre entidades
•Para mapear relacionamentos,JPA usa informações da estrutura do
código Java e anotações mínimas (serão usados defaults onde possível)
•A cardinalidade define o número de entidades em cada lado. Podem ser
mapeados “muitos” e “um” resultando em quatro possibilidades:
•Um para muitos
•Muitos para um
•Um para um
•Muitos para muitos.
•As duas primeiras são equivalentes, portanto há três associações:
•@ManyToOne / @OneToMany

•@OneToOne

•@ManyToMany
JAVAEE7 @ManyToOne unidirecional
@Entity
public class Produto {
@Id @GeneratedValue
int codigo;
String nome;
double preco;
public int getCodigo() {
return codigo;
}
public void setCodigo(int codigo) {
this.codigo = codigo;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
...
@Entity
public class Item {
@ManyToOne
private Produto produto;
public Produto getProduto() {
return produto;
}
public void setProduto(Produto produto) {
this.produto = produto;
}
public double subtotal() {
return produto.getPreco() * quantidade;
}
...
Classe Produto não sabe da
existência da associação*
Método de negócio que
utiliza-se da associação para
realizar uma operação
* Essas anotações são insuficientes para a geração automática do esquema (as tabelas devem existir antes)
JAVAEE7 Associações bidirecionais
•Se as anotações @OneToOne, @ManyToMany e @ManyToOne forem
usadas em associações bidirecionais é necessário especificar anotações de
ambos os lados e utilizar o atributo mappedBy para informar o atributo da
outra classe que faz a associação
•O diagrama abaixo ilustra algumas associações bidirecionais.
@OneToOne 

CPF cpf;
@OneToOne(mappedBy="cpf") 

Cliente cliente;
@ManyToMany

Set<Turma> turmas;
@ManyToMany(mappedBy="turmas") 

Set<Aluno> alunos;
@ManyToOne 

Item item;
@OneToMany(mappedBy="item")

Set<Produto> produtos;
JAVAEE7 @ManyToOne bidirecional
@Entity
public class Pedido {
@OneToMany(mappedBy="pedido")
private Set<Item> itens = new HashSet<Item>();
public Set<Item> getItens() {
return itens;
}
public void setItens(Set<Item> itens) {
this.itens = itens;
}
public void addItem(Item item) {
itens.add(item);
item.setPedido(this);
}
public double subtotal() {
double subtotal = 0;
for (Item item : itens) {
subtotal += item.subtotal();
}
return subtotal;
}
...
@Entity
public class Item {
@ManyToOne
private Pedido pedido;
public Pedido getPedido() {
return pedido;
}
public void setPedido(Pedido pedido) {
this.pedido = pedido;
}
public double subtotal() { ... }
...
Utilitário para facilitar a adição de itens na
associação (atualiza os dois lados da associação)
Método de negócio que utiliza-se da associação
para realizar uma operação
JAVAEE7 @ManyToMany bidirecional
@Entity
public class Aluno {
@Id @GeneratedValue
private int id;
@ManyToMany(mappedBy="alunos")
private Set<Turma> turmas;
public Set<Turma> getTurmas() {
return turmas;
}
public void setTurmas(Set<Turma> turmas) {
this.turmas = turmas;
}
public void matricular(Turma turma) {
turmas.add(turma);
if(!turmas.contains(turma))
turma.addAluno(this);
}
...
}
@Entity
public class Turma {
@Id @GeneratedValue
private int id;
@ManyToMany(mappedBy="turmas")
private Set<Aluno> alunos;
public Set<Aluno> getAlunos() {
return alunos;
}
public void setAlunos(Set<Turma> turmas) {
this.alunos = alunos;
}
public void addAluno(Aluno aluno) {
alunos.add(aluno);
if(!alunos.contains(aluno))
aluno.matricular(this);
}
...
}
Métodos utilitários para adicionar alunos e turmas
JAVAEE7 Relacionamentos um-para-um
•Objetos em um relacionamento com alto grau de dependência. No modelo
relacional isto pode ser implementado de três maneiras:
•Dois objetos, uma única tabela (dados em colunas da mesma tabela)
•Um objeto, duas tabelas (dados em colunas de outra tabela)
•Dois objetos, duas tabelas unidas por associação
•Em JPA, a terceira estratégia pode ser implementada usando @ManyToOne
(unidirecional com @UniqueConstraint) ou mais facilmente usando @OneToOne
(via chave estrangeira ou primária).
•As duas primeiras estratégias não são relacionamentos entre entidades, mas
associações com instâncias ou coleções. Em JPA, a primeira é implementada usando
@Embeddable e a segunda com @SecondaryTable.
JAVAEE7 @OneToOne bidirecional
@Entity
public class Cliente {
@OneToOne(mappedBy="cliente")
private CPF cpf;
public CPF getCPF() {
return cpf;
}
public void setCPF(CPF cpf) {
this.cpf = cpf;
}
...
@Entity
public class CPF {
@OneToOne
private Cliente cliente;
public Cliente getCliente() {
return cliente;
}
public void setCliente(Cliente
cliente) {
this.cliente = cliente;
}
...
Só é necessário informar
o mappedBy em um dos
lados da associação
JAVAEE7 Tipos das Coleções: List ou Set
•Relacionamentos @ManyToOne e @ManyToMany envolvem coleções que
normalmente são declarados como Set ou List
•O mapeamento natural para registros em uma tabela é java.util.Set,
porque Sets não possuem uma ordem especifica e não podem ser
duplicados
•Sets podem ser ordenados no query usando @OrderBy e na instância
usando uma implementação ordenada como TreeSet
•Pode-se usar List quando o índice é importante ou para compatibilidade
com outros componentes (ex: componentes Primefaces que esperam List)
JAVAEE7 Mapas
•E possível mapear uma coleção a um mapa usando @MapKey e representando
a coleção como um java.util.Map.
•Um Map contem um Set de chaves e uma Collection de valores, e é indicado
situações nas quais é mais eficiente recuperar um objeto através de uma chave.
•A chave default é a chave-primária dos objetos da coleção:
@Entity
public class LojaVirtual {
...
@OneToMany(mappedBy="lojaVirtual")
@MapKey // indexado pela chave primaria
public Map<Long, Cliente> clientes = new HashMap <>();
...
}
JAVAEE7 Mapas
•Usando o atributo name é possível indexar por outras propriedades dos
objetos da coleção:
•O mapeamento da chave também pode ser feito através das colunas, em vez
dos atributos, usando @MapKeyColumn e @MapKeyJoinColumn.
•Existem ainda mais duas anotações para @MapKey
•@MapKeyEnumerated, se a chave for uma enumeração
•@MapKeyTemporal, se a chave for uma data ou Timestamp.
@Entity
public class LojaVirtual {
...
@OneToMany(mappedBy="lojaVirtual")
@MapKey(name="cpf") // indexado pelo CPF
public Map<String, Cliente> clientes = new HashMap<>();
...
}
Veja mais detalhes
na documentação
JAVAEE7 Componentes @Embeddable
•Entidades são objetos persistentes que têm identidade no banco
•Objetos que contém dados persistentes mas não têm identidade unívoca
no banco são identificados pelo seu estado, ou valor (value objects).
•Em JPA são anotados como @Embeddable
•No modelo de domínio representam um objeto independente, mas no modelo
relacional são apenas algumas colunas de uma tabela.
•São componentes da entidade que possui a tabela e declarados como
atributos anotados como @Embedded
•Muitas associações 1-1 podem ser implementadas de maneira mais
eficiente como objetos embutidos.
JAVAEE7 Componentes @Embeddable
Cliente
nome
email
cartao
Endereco
Rua
CEP
Cidade
enderecoEntrega

enderecoCobranca
nome email cartao ent_rua ent_cep ent_cidade cob_rua cob_cep cob_cidade
:Ciente enderecoEntrega:Endereco enderecoCobranca:Endereco
<<Entidade>> <<Componente>>
@Entity @Embeddable
@Embedded
•Uma única tabela contém dados dos objetos Cliente e Endereco
•Endereco é um componente de Cliente, e declarado como @Embeddable
•Um Cliente tem dois Enderecos e cada associação é declarada como @Embedded
JAVAEE7 Componentes @Embeddable
@Entity
@Table(name="CLIENTE")
public class Cliente {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long codigo;
private String nome;
...
@Embedded
private Endereco enderecoCobranca;
@Embedded
@AttributeOverrides({
@AttributeOverride(name="rua", column=@Column(name="ENT_RUA")),
@AttributeOverride(name="cep", column=@Column(name="ENT_CEP")),
@AttributeOverride(name="cidade", column=@Column(name="ENT_CIDADE")),
})
private Endereco enderecoEntrega;
...
@Embeddable
public class Endereco {
@Column(name="COB_RUA")
private String rua;
@Column(name="COB_CEP")
private String cep;
@Column(name="COB_CIDADE")
private String cidade;
...
}
reusa mesma classe Endereco,
mas redefine mapeamentos
JAVAEE7 @Embeddable collections
•Se uma entidade contém uma coleção de componentes embutidos, ou tipos
básicos (que não são entidades) deve ser anotado com @ElementCollection
•A entidade abaixo contém uma coleção de objetos Endereco, que são
@Embeddable, e uma coleção de Strings:
@Entity
public class Representantes {
...
@ElementCollection
private Set<Endereco> enderecos = new HashSet<>();
@ElementCollection
private Set<String> emails = new HashSet<>();
...
}
JAVAEE7 Chaves compostas
•@Embeddable pode ser usado na criação de chaves compostas. Por
exemplo, uma chave-primária que consiste de dois campos do tipo String:
•Ela pode ser usada em uma entidade anotada com @EmbeddedId:
•É responsabilidade da aplicação gerenciar o estado da chave composta, para
que a persistência transitiva ocorra corretamente.
@Entity @Table(name = "DEPENDENCIA")
public class Dependencia {
@EmbeddedId private DependenciaId id;
// ...
}
@Embeddable
public class DependenciaId {
@Column(name = "APP_ID") private String appID;
@Column(name = "GROUP_ID") private String groupID;
//...
}
JAVAEE7 Mapeamento de enumerações
•Enumerações podem ser persistidas se marcadas com @Enumerated
public enum Regiao {

NORTE, NORDESTE, SUL, SUDESTE, CENTRO_OESTE;

}
•Exemplo:
@Entity

public class SalaDeCinema { ...

@Enumerated(EnumType.STRING)

private Regiao regiao;
•O EnumType default é ORDINAL: grava número no registro da tabela.
STRING é não é afetado pela ordem das constantes (grava texto na tabela).
JAVAEE7 Mapeamento de uma classe a duas tabelas
•Usa-se @SecondaryTable para construir uma entidade que obtém
seus dados de duas tabelas.
•No exemplo abaixo a entidade Usuario está mapeado a uma
tabela principal (USUARIOS) e uma tabela secundária (IMAGENS)
JAVAEE7 Mapeamento de uma classe a duas tabelas
•@Table é a tabela principal e @SecondaryTable a tabela secundária, que
indica coluna(s) contendo a chave primária usada(s) para realizar a junção.
•@PrimaryKeyJoinColumn contém: chave primária da tabela principal, chave
referenciada na tabela secundária (ou apenas o primeiro se forem iguais). O
atributo da segunda tabela informa a tabela e coluna a ser mapeada
@Entity
@Table(name="USUARIOS")
@SecondaryTable(name="IMAGENS",
pkJoinColumns = @PrimaryKeyJoinColumn(name="USUARIO_ID",
referencedColumnName="IMG_ID"))
public class Usuario implements Serializable {
...
@Id Column(name="USUARIO_ID")
private Long userId;
@Column(table="IMAGENS", name="URL_IMG", nullable=true)
private String avatar; ...
JAVAEE7 Transitividade da persistência
•Relacionamentos em JPA são implementados em Java puro, e não são
gerenciados pelo container por default.Alterações precisam ser sincronizadas:
Pedido p = new Pedido();

Item i = new Item();

p.addItem(i); // atualizando o pedido

item.setPedido(p); // atualizando o item (se bidirecional)
•As entidades precisam ser persistentes.Tentar adicionar uma entidade
transiente a uma entidade persistente causa TransientObjectException.
•persist() ou merge() dentro de um contexto transacional resolve o problema:
em.persist(p);

em.persist(i);
JAVAEE7 Transitividade da persistência
•Pode-se configurar persistência transitiva no JPA usando o atributo
cascade das anotações de relacionamentos.
•Para propagar a inserção de entidades use CascadeType.PERSIST:
@OneToMany(cascade={CascadeType.PERSIST}, 

mappedBy="item" )

private Set<Item> itens = new HashSet<Item>();
•Quando um Pedido for persistido no banco, itens que estiverem na
hierarquia de objetos também serão persistidos automaticamente.
JAVAEE7 CascadeType
•O atributo cascade recebe um array de opções CascadeType
•PERSIST – propaga operações persist() e merge() em objetos novos
•MERGE – propaga operações merge()
•REMOVE – propaga operações remove()
•DETACH – propaga operações detach()
•REFRESH – propaga operações refresh()
•ALL – propaga todas as operações. Declarar cascade=ALL é o mesmo que
declarar cascade={PERSIST, MERGE, REMOVE, REFRESH, DETACH}
•Um uso típico é PERSIST + MERGE, que garante inserts e updates transitivos
@OneToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE})
•Se a remoção de um Pedido exigir a remoção de seus Itens um REMOVE é
necessário. Pode-se usar ALL para que todas as operações sejam transitivas
JAVAEE7 Lazy loading
•Lazy loading um padrão de design usado para adiar a inicialização de um
objeto para quando ele for realmente necessário
•ORMs usam estratégias de lazy loading para otimizar pesquisas
•Contribui para a eficiência da aplicação se usado corretamente
•Um query, por default, retorna uma coleção de proxies para seus elementos (e
não a coleção preenchida pelos próprios elementos)
•Se um cliente fora do contexto transacional tentar acessar um elemento da
coleção, haverá uma exceção de inicialização lazy. O comportamento default
depende do provedor usado
•Hibernate lança LazyInitializationException.
•EclipseLink captura a exceção e abre nova conexão ao banco para obter os dados
JAVAEE7 Configuração de lazy loading
•É possível controlar o lazy loading configurando a recuperação default
como eager (ansiosa), em vez de lazy (preguiçosa) de duas maneiras:
•Através de mapeamento (estabelece um default para todas as situações)
•Através de instruções no query (a cada consulta)
•O atributo fetch=FetchType das anotações de relacionamentos configura o
modo eager como default para todas as operações
@OneToMany(mappedBy="pedido", fetch=FetchType.EAGER)

private Set<Item> itens = new HashSet<Item>();
•No query, um fetch join devolve a coleção com todos os seus elementos
select p from Pedido p join fetch p.itens
JAVAEE7 Exercícios
•7. Implemente o mapeamento Movie-Director da Hierarquia 2
•8. Implemente os mapeamentos de Cliente-Pedido-Item-Produto na
Hierarquia 3
•9. Implemente todos os mapeamentos da Hierarquia 4
•Use @Embedded para o relacionamento Etapa-Localidade
•Use @OneToOne para o relacionamento Participante-Ingresso
•Implemente uma enumeração para guardar o status do ingresso com as
constantes PAGO e NAO_PAGO
•O relacionamento Corrida-Etapa é unidirecional
•10. Implemente o relacionamento Assunto-Assunto na Hierarquia 35
JAVAEE7
JPA
javapersistenceapi
6
mapeamentodeherança
JAVAEE7 Mapeamento de herança
•Entidades são objetos e suportam herança de classes, associações e
queries polimórficos. Podem ser abstratas ou concretas, e podem ser
subclasses ou superclasses de classes que não são entidades.
•Mas não existe herança em tabelas. Herança é o descasamento mais
visível entre os mundos relacional e orientado a objetos.
•O mundo OO possui relacionamento “é um” e “tem um”, enquanto que o
mundo relacional apenas possui relacionamento “tem um”.
•Há três estratégias para lidar com esse problema (sugeridas por Scott
Ambler, 2002). Essas estratégias são adotadas na arquitetura do JPA.
JAVAEE7 MappedSuperclass
•Entidades podem ter superclasses que não são entidades
•Se a superclasse possuir a anotação @MappedSuperclass, seus atributos serão
herdados e farão parte do estado persistente das subclasses
•Uma @MappedSuperclass também pode incluir anotações de persistência nos
seus atributos, mas não é uma entidade e não pode ser usada com operações de
EntityManager ou Query (não está mapeada a uma tabela)
•Apenas as subclasses de entidades concretas são mapeadas a tabelas e podem
conter colunas correspondentes aos atributos herdados.
@MappedSuperclass
public class Quantia {
@Id protected Long id;
protected BigDecimal valor; ...
}
@Entity public class Pagamento extends Quantia { ... }
@Entity public class Divida extends Quantia { ... }
JAVAEE7 @Inheritance e InheritanceType
•A anotação javax.persistence.Inheritance é usada para configurar o
mapeamento de herança entre entidades em JPA
•Elas implementam as três estratégias citadas que são selecionadas através
das constantes da enumeração InheritanceType:
public enum InheritanceType { 

SINGLE_TABLE,

JOINED,

TABLE_PER_CLASS 

};
•A estratégia default é SINGLE_TABLE, que mapeia todas as classes de uma
hierarquia a uma única tabela no banco de dados
•Há muitas possibilidades de configuração (mostraremos as mais simples)
JAVAEE7 Tabela por Classe Concreta: TABLE_PER_CLASS
Pagamento
id

valor
Credito

numero
validade
<<Entidade>>
Debito

banco
conta
<<Entidade>>
@Id declarado apenas na superclasse
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class Pagamento {
@Id @GeneratedValue private long id;
}
@Entity
public class Debito extends Pagamento {...}
ID NUMERO VALIDADE
5
ID BANCO CONTA
5
CREDITO
DEBITO
<<Entidade>>
JAVAEE7 Tabela por Classe Concreta: TABLE_PER_CLASS
•Tem como vantagem o mapeamento direto entre classe e tabela normalizada.
•A gravação é realizada via classe concreta, mas a pesquisa pode ser polimórfica,
via classe abstrata e com resultado que inclui as subclasses concretas
•Ex: filtrar Pagamentos por valor, sem precisar saber se Crédito ou Débito:
select p from Pagamento p where p.valor > 1000
•A desvantagem dessa estratégia é a complexidade e ineficiência dos queries
gerados. Exemplo de SQL gerado no Hibernate:
select ID, VALOR, NUMERO, VALIDADE, BANCO, CONTA from (

select ID, VALOR, NUMERO, VALIDADE, 

null as BANCO, null as CONTA from CREDITO 

union select ID, VALOR, null as NUMERO, null as VALIDADE, 

BANCO, CONTA from DEBITO) where VALOR > 1000
JAVAEE7 Tabela por hierarquia: SINGLE_TABLE
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TIPO")
public abstract class Pagamento {
@Id @GeneratedValue private long id;
}
ID TIPO VALOR NUMERO VALIDADE BANCO CONTA
5 crd 100.0 23459403 12/15 null null
6 deb 100.0 null null 1234-5 993423-3
PAGAMENTO
Coluna (@DiscriminatorColumn)
presente na tabela mas sem
mapeamento na classe
@Entity @DiscriminatorValue("deb")
public class Debito extends Pagamento {...}
Pagamento
id

valor
Credito

numero
validade
<<Entidade>>
Debito

banco
conta
<<Entidade>>
<<Entidade>>
JAVAEE7 Tabela por hierarquia: SINGLE_TABLE
•Mapeia uma hierarquia de classes inteira a uma tabela
•A tabela precisa ter colunas para todas as propriedades de todas as classes.
•A vantagem são pesquisas polimórficas mais eficientes, já que tudo acontece
em uma única tabela. Este é o SQL conceitual para um query polimórfico:
select ID, VALOR, BANCO, CONTA, NUMERO, VALIDADE 

from PAGAMENTO 

where VALOR > 1000
•Em query na classe concreta, o provedor de persistência poderá gerar este SQL:
select ID, VALOR, BANCO, CONTA, NUMERO, VALIDADE 

from PAGAMENTO 

where TIPO = 'deb' and VALOR > 1000
•A principal desvantagem dessa estratégia é que as tabelas não são normalizadas
JAVAEE7 Tabela por subclasse: JOINED
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public abstract class Pagamento {
@Id @GeneratedValue private long id;
}
Pagamento
id

valor
Credito

id

numero
validade
ID NUMERO VALIDADE
5
<<Entidade>>
Debito

id

banco
conta
<<Entidade>>
ID BANCO CONTA
5
CREDITO
DEBITO
@Entity
public class Debito extends Pagamento {...}
ID VALOR
5
PAGAMENTO ID é PK e FK
(default)
<<Entidade>>
JAVAEE7 Tabela por subclasse: JOINED
•Uma Classe abstrata ou concreta = Uma Tabela distinta; relacionamento
através de equivalência de chave primária e estrangeira (default)
•Modelo relacional normalizado
•Evolução sem efeitos colaterais: novas classes e tabelas podem ser criadas sem
afetar existentes
•Aplicação de restrições de integridade mais simples
•Performance da pesquisa polimórfica ainda é baixa em hierarquias complexas
(usa dados de todas as tabelas envolvidas)
•Os provedores de persistência* geralmente geram SQL com outer join para
pesquisas polimórficas e inner join para pesquisas em classes concretas
*Hibernate e EclipseLink
JAVAEE7 Qual estratégia?
Há necessidade
de consultas
polimórficas?
Hierarquia de
classes é pequena?
Tabela por Hierarquia
InheritanceType.SINGLE_TABLE
Tabela por Subclasse
InheritanceType.JOINED
Tabela por Classe Concreta
InheritanceType.TABLE_PER_CLASS
Tabelas tem
que ser
normalizadas?
NÃO*
* Se houver suporte no provedor (o suporte é opcional)
SIM
SIM
NÃO
NÃO
SIM
(default)
JAVAEE7 Exercícios
•11. Implemente um mapeamento da hierarquia Usuario-
Operador-Cliente (Hierarquia 3) usando qualquer uma das três
estratégias
•12. Implemente uma mapeamento da hierarquia Exemplar-
Exemplar Eletrônico-Exemplar Impresso (Hierarquia 5) usando
uma estratégia diferente
JAVAEE7
JPA
javapersistenceapi
7
queriesjpql
JAVAEE7 Consultas (queries)
•Consultas podem ser construídas para recuperar entidades a
partir de critérios baseados em seu conteúdo
•JPA possui duas estratégias nativas:
•JPQL – linguagem similar a SQL baseada em comandos de texto
•Criteria – API usada para construir consultas usando objetos.
•JPQL é geralmente mais fácil de aprender, mas Criteria permite a
criação de queries com maior potencial de reuso e evolução, além
de ser recomendada para queries dinâmicas
JAVAEE7 Cláusulas
•Consultas em bases de objetos têm princípios similares a
consultas em bancos de dados
•A cláusula mais importante é FROM, que declara o escopo da
pesquisa. Na API Criteria é representada por um objeto raiz.
•A clausula SELECT indica o que está sendo selecionado dentro do
escopo FROM. Em JPA pode-se selecionar entidades, seus atributos, e
resultados de operações realizados sobre elas
•A cláusula opcional WHERE declara filtros que restringem os
resultados da pesquisa. Sem WHERE todos os elementos do escopo
declarado em FROM serão recuperados
JAVAEE7 Joins
•Operação que amplia o domínio da função para incluir objetos
de um relacionamento usadas em JPQL e Criteria
•Consultas que navegam no grafo de objetos usando o operador
ponto (ex: cliente.pedido.item) escondem joins implícitos
•Joins em grafos de objetos são similares mas não idênticos a
joins no mundo relacional. Há três tipos em JPA. :
•Lazy Inner Joins (default – joins implícitos são sempre inner joins)
•Lazy Outer (ou Left) Joins
•Eager (ou Fetch) Joins (que podem ser inner ou outer)
JAVAEE7 Inner Joins e Outer joins
•Inner Joins consideram apenas resultados que contém o
relacionamento
•Elementos que não possuem o relacionamento declarado são filtrados
•Exemplo: uma consulta sobre objetos Cliente para obter o total de
Pedidos (relacionamento Cliente-Pedido)
•Um inner join não retorna os clientes que não têm pedidos.
•Um outer join retorna tudo, mesmo que o cliente seja null
JAVAEE7 Lazy Joins e Eager Joins
•A inicialização dos elementos de uma coleção é Lazy por default
•Uma coleção obtida em uma consulta pode conter apenas um proxy
para cada elemento (é preciso fazer novas consultas para obter cada um)
•O comportamento exato é dependente do contexto transacional e
também do provedor de persistência utilizado
•Eager Joins garantem que a coleção seja inicializada antes do uso
•Depois da consulta a coleção está povoada com todos os seus elementos
•Isto pode ser pré-configurado no mapeamento, mas é mais eficiente
poder selecionar esse comportamento durante a consulta
JAVAEE7 JPQL (JPA Query Language)
•Linguagem de recuperação de dados
•Similar a linguagens de query de objetos (HQL, EJB-QL, etc.) que a precederam
•Parece com SQL mas opera sobre objetos e não tabelas
•Consultas são objetos da classe Query/TypedQuery e podem ser construídas
através de métodos de EntityManager
•As instruções do query podem ser passadas diretamente para o método
createQuery() como parâmetro do tipo String.
@PersistenceContext
EntityManager em;
...
TypedQuery query =
em.createQuery("SELECT p FROM Produto p", Produto.class);
JAVAEE7 Named queries
•O query pode também ser declarado previamente em anotações
@NamedQuery em cada entidade:
•Associado a um identificador, referenciado em createNamedQuery()
@Entity
@NamedQueries({
@NamedQuery(name="selectAllProdutos",
query="SELECT p FROM Produto p")
})
public class Produto implements Serializable { ... }
TypedQuery query =
em.createNamedQuery("selectAllProdutos", Produto.class);
JAVAEE7 Consultas parametrizadas
•Os parâmetros podem ser declarados em JPQL usando
identificadores numéricos ou nomes precedidos por “:”:
•Se houver parâmetros, eles podem ser preenchidos através de um
ou mais métodos setParameter() antes de executar o query.
TypedQuery query = 

em.createQuery("SELECT p FROM Produto p WHERE p.preco > :maximo", 

Produto.class);
query.setParameter("máximo", 1000);
JAVAEE7 Métodos que executam queries
•Retornam resultados
•Se o resultado for uma coleção, pode-se usar getResultList():
•Se retornar apenas um item (por exemplo, se o produto for selecionado
por ID ou um campo unívoco), pode-se usar getSingleResult():
•Há outros métodos de execução não fazem pesquisa mas são usados
para remoção ou atualização, como executeUpdate()
List<Produto> resultado = query.getResultList();
Produto produto = query.getSingleResult();
JAVAEE7 Sintaxe de uma operação SELECT
•A principal operação de JPQL é SELECT, que tem a seguinte sintaxe geral
cláusula_select cláusula_from

[cláusula_where] [cláusula_group_by] [cláusula_having] [cláusula_order_by]
SELECT p.nome
FROM Produto AS p
WHERE p.codigo = '123'
Define o contexto da pesquisa e declara
p como alias da entidade Produto
Seleciona valores no contexto da entidade p
Parâmetro
Restrição da seleção
SELECT p 

FROM Produto p 

WHERE p.nome = :n
Alias (AS é opcional)
Parâmetro de query
Seleção de entidades
(cláusulas opcionais)
JAVAEE7 Cláusula FROM
•A cláusula FROM define o escopo informando qual ou quais os objetos
que estão sendo pesquisados, e declara aliases usados no resto do query.
•Cada alias tem um identificador e um tipo.
•O identificador é qualquer palavra não-reservada e o tipo é o nome da
entidade identificada como @Entity.
•A palavra-chave AS (opcional) conecta o tipo ao identificador
•A cláusula FROM também pode selecionar múltiplos objetos e atributo e
incluir vários conectores de JOIN (inner join, left outer join).
... FROM Produto AS p
Tipo	(Entidade) Identificador	(alias)
JAVAEE7 Cláusula SELECT
•Informa o que se deseja obter. Pode retornar
•entidades,
•atributos dos objetos,
•resultados de expressões,
•tuplas envolvendo atributos, entidades e resultados de expressões
•Pode ser seguida de DISTINCT para eliminar valores duplicados
•SELECT utiliza o alias declarado na cláusula FROM:
SELECT p FROM Produto p
SELECT DISTINCT p FROM Produto p
SELECT p.codigo FROM Produto p
SELECT DISTINCT p.codigo FROM Produto p
JAVAEE7 Cláusula WHERE
•É opcional e restringe os resultados da pesquisa com base em uma ou mais
expressões condicionais concatenadas.As expressões podem usar:
•literais (strings, booleanos ou números),
•identificadores (declarados no FROM),
•operadores,
•funções
•parâmetros identificados por número (?1, ?2) ou identificador (:nome, :item).
•Os literais usados nas pesquisas podem ser:
•Strings, representados entre apóstrofes: 'nome'
•Números, que têm mesmas regras de literais Java long e double
•Booleanos, representados por TRUE e FALSE (case-insensitive)
JAVAEE7 Operadores de WHERE
•Navegação .
•Expressões matemáticas +, -, *, /
•Expressões de comparação =, >, >=, <, <=, <>
•Operadores lógicos NOT,AND, OR
•Outros operadores: [NOT] BETWEEN, [NOT] IN, [NOT] LIKE, IS [NOT]
NULL, IS [NOT] EMPTY, [NOT] MEMBER
•O operador LIKE possui operadores adicionais:
•_ representa um único caractere
•% representa uma seqüência de zero ou mais caracteres
• caractere de escape (necessário para usar _ ou %) literalmente
JAVAEE7 Funções
•Funções podem aparecer em cláusulas WHERE ou SELECT:
•Manipulação de strings (WHERE): CONCAT, SUBSTRING,TRIM,
LOWER, UPPER, LEADING,TRAILING, BOTH, LENGTH, LOCATE
•Funções aritméticas (WHERE): ABS, SQRT, MOD, SIZE
•Data e hora (WHERE): CURRENT_DATE, CURRENT_TIME,
CURRENT_TIMESTAMP
•Funções de agregação (SELECT): COUNT, MAX, MIN,AVG, SUM
JAVAEE7 Exemplos
•Encontre todos os produtos que são chips e cuja margem de lucro é
positiva
SELECT p 

FROM Produto p 

WHERE (p.descricao = 'chip' AND (p.preco - p.custo > 0)
•Encontre todos os produtos cujo preço é pelo menos 1000 e no máximo
2000
SELECT p

FROM Produto p 

WHERE p.preco BETWEEN 1000 AND 2000
JAVAEE7 Exemplos
•Encontre todos os produtos cujo fabricante é Sun ou Intel
SELECT p

FROM Produto p 

WHERE p.fabricante IN ('Intel', 'Sun')
•Encontre todos os produtos com IDs que começam com 12 e
terminam em 3
SELECT p

FROM Produto p 

WHERE p.id LIKE '12%3'
JAVAEE7 Exemplos
•Encontre todos os produtos que têm descrições null
SELECT p

FROM Produto p 

WHERE p.descricao IS NULL
•Encontre todos os pedidos que não têm itens (coleção)
SELECT pedido 

FROM Pedido pedido 

WHERE pedido.itens IS EMPTY
JAVAEE7 Exemplos
•Retorne os pedidos que contem um determinado item (passado como
parâmetro)
SELECT pedido

FROM Pedido pedido 

WHERE :item IS MEMBER pedido.itens
•Encontre produtos com preços entre 1000 e 2000 ou que tenham código
1001
SELECT p

FROM Produto p 

WHERE p.preco BETWEEN 1000 AND 2000 OR codigo = 1001
JAVAEE7 Exemplos com relacionamentos
•Selecione todos os clientes com pedidos que tenham total maior que
1000:
SELECT c 

FROM Cliente c, IN(c.pedidos) p 

WHERE p.total > 1000
•O mesmo query poderia ser escrito desta forma, expondo o join:
SELECT c 

FROM Cliente c 

INNER JOIN c.pedidos AS p 

WHERE p.total > 1000
JAVAEE7 Exemplos com relacionamentos
•Lances onde o item de categoria iniciando em “Celular” tenha obtido lance >1000:
SELECT lance

FROM Lance lance 

WHERE lance.item.categoria.nome LIKE 'Celular%' 

AND lance.item.lanceObtido.total > 1000
•Queries equivalentes. O primeiro expõe um dos joins e o segundo expõe todos:
SELECT lance

FROM Lance lance

JOIN lance.item item 

WHERE item.categoria.nome LIKE 'Celular%'

AND item.lanceObtido.total > 1000
SELECT lance

FROM Lance AS lance

JOIN lance.item AS item 

JOIN item.categoria AS cat 

JOIN item.lanceObtido AS lanceVencedor 

WHERE cat.nome LIKE 'Celular%'

AND lanceVencedor.total > 1000
JAVAEE7 Exemplos usando funções
•Encontre a média do total de todos os pedidos:
SELECT AVG(pedido.total)

FROM Pedido pedido
•Obtenha a soma dos preços de todos os produtos dos pedidos feitos no
bairro de Botafogo:
SELECT SUM(item.produto.preco) 

FROM Pedido pedido 

JOIN pedido.itens item 

JOIN pedido.cliente cliente 

WHERE cliente.bairro = 'Botafogo' 

AND cliente.cidade = 'Rio de Janeiro'
JAVAEE7 Exemplos usando funções
•Obtenha a contagem de clientes agrupadas por bairro:
SELECT cliente.bairro, COUNT(cliente) 

FROM Cliente cliente

GROUP BY cliente.bairro
•Obtenha o valor médio dos pedidos, agrupados por pontos, para os
clientes que têm entre 1000 e 2000 pontos:
SELECT c.pontos, AVG(pedido.total) 

FROM Pedido pedido 

JOIN pedido.cliente c 

GROUP BY c.pontos 

HAVING c.pontos BETWEEN 1000 AND 2000
JAVAEE7 Exemplos com subqueries
•É possível usar os resultados de um query como parâmetro de
outro através de subqueries. O query abaixo usa como restrição o
resultado de um query que será testado com EXISTS.
•"Obtenha os empregados que são casados com outros
empregados"
SELECT DISTINCT emp 

FROM Empregado emp 

WHERE EXISTS (SELECT conjuge 

FROM Empregado conjuge

WHERE conjuge = emp. conjuge)
JAVAEE7 Exemplos com subqueries: All/Any
•ALL e ANY são usados com subqueries
•ALL retorna true se todos os valores retornados forem true
•ANY só retorna true se resultado for vazio ou se todos os valores forem false
•"Retorne apenas os produtos cujo preço seja maior que o valor incluído
em todos os orçamentos"
SELECT produto 

FROM Produto p 

WHERE p.preco > ALL(SELECT o.item.preco 

FROM Orcamento o 

WHERE o.item.codigo = p.codigo)
JAVAEE7 Queries que retornam tuplas
•Queries que retornam múltiplos valores têm resultados
armazenados em arrays de objetos
• Cada índice do array corresponde respectivamente ao item selecionado,
na ordem em que é expresso em JPQL
•Exemplo: a query abaixo retorna três valores: um Long, um String e
um Diretor, que é uma entidade, respectivamente.
@Entity class Filme {
@Id private Long id;
private String imdb;
private String titulo;
@ManyToMany
private Diretor diretor;
...
}
SELECT f.id, f.titulo, d 

FROM Filme f join f.diretores d 

WHERE d.nome LIKE ‘%Allen’ @Entity class Diretor {
@Id private Long id;
private String nome;
...
}
JAVAEE7 Queries que retornam tuplas
•A execução so query irá retornar cada elemento como um array do tipo
Object[] onde cada valor será armazenado em um índice
•Se houver mais de um resultado, o tipo retornado será List<Object[]>
•Para obter os dados da query anterior pode-se usar:
List<Object[]> resultado =
(List<Object[]>)query.getResultAsList();
for(Object obj : resultado) {
Long id = (Long)obj[0];
String titulo = (String)obj[1];
Diretor diretor = (Diretor)obj[2];
...
}
JAVAEE7 Tuplas como DataTransferObject (DTO)
•Queries que retornam tuplas podem ter o objetivo de gerar
relatórios, ou para coletar dados para uma interface
•Os dados podem ser guardados em um objeto especialmente criado
para recebê-los:
package com.acme.filmes;
public class DataTransferObject {
private Long id;
private String titulo;
private Diretor diretor;
public DataTransferObject(Long id, String titulo, Diretor diretor) {
this.id = id;
this.titulo = titulo;
this.diretor = diretor;
}
...
}
JAVAEE7 Tuplas como DataTransferObject (DTO)
•O objeto pode então ser instanciado dentro do loop:
List<Object[]> resultado =
(List<Object[]>)query.getResultAsList();
for(Object obj : resultado) {
Long id = (Long)obj[0];
String titulo = (String)obj[1];
Diretor diretor = (Diretor)obj[2];
DataTransferObject dto =
new DataTransferObject(id, titulo, director);
// envia dto para algum lugar
}
JAVAEE7 Tuplas como DataTransferObject (DTO)
•Há uma sintaxe de SELECT que elimina a necessidade de escrever todo
esse código, chamando o construtor diretamente dentro do query:
•JPA 2.1 requer que o construtor use o nome qualificado da classe
•O query retorna uma List<DataTransferObject> em vez de
List<Object[]>, que pode ser retornada diretamente para o cliente:
SELECT new com.acme.filmes.DataTransferObject(f.id, f.titulo, d) 

FROM Filme f join f.diretores d 

WHERE d.nome LIKE ‘%Allen’
@Named public class ManagedBean {
public List<DataTransferObject> getDataToPopulateComponent() {
...
return query.getResultAsList();
} ...
}
JAVAEE7 Tuplas em JPA Criteria
•CriteriaQuery oferece outra alternativa de solução para este
problema com a interface javax.persistence.Tuple
•Os resultados ainda precisam ser extraídos individualmente, mas
são retornados em um objeto Tuple (em vez de Object[])
•O conteúdo de Tuple pode ser recuperado como uma List:
tupla.get(0), tupla.get(1), etc.
JAVAEE7 Named Queries
•Queries podem ser declarados em anotações e recuperadas pelo nome
•Isto, em geral é uma boa prática porque mantém todos os queries juntos, e
pode facilitar a manutenção deles
•Por outro lado, os mantém distante do código que cria os queries e
preenche os parâmetros, que pode dificultar o uso.
•Para declarar queries desta forma, use a anotação @NamedQueries:
@Entity
@NamedQueries({
@NamedQuery(name="produtoMaisBarato",
query="SELECT x FROM Produto x WHERE x.preco > ?1"),
@NamedQuery(name="produtoPorNome",
query="SELECT x FROM Produto x WHERE x.nome = :nomeParam")
})
public class Produto { ... }
JAVAEE7 Uso de Named Queries
•Para usar, chame o query pelo nome quando usar o EntityManager através
do método createNamedQuery(), e preencha seus parâmetros se houver:
EntityManager em = ...
Query q1 = em.createNamedQuery("produtoMaisBarato");
q1.setParameter(1, 10.0);
List<Produto> resultado1 = q1.getResultList();
Query q2 = em.createNamedQuery("produtoPorNome");
q2.setParameter("nomeParam", 10.0);
List<Produto> resultado2 = q2.getResultList();
JAVAEE7 Exercícios
•13. Escreva os seguintes queries em JPQL usando a Hierarquia 5:
•Todos os livros com idioma = PT ou EN
•Livros cujo título tenha a palavra "the" e id entre 2 e 10
•Livros que tenham um autor chamado "John"
•Autores que tenham mais de um livro
•Editoras que tenham mais de um título em idioma = EN
•14. Escreva os seguintes queries usando a Hierarquia 2:
•Todos os filmes com duração maior que 100 minutos
•Filmes produzidos entre 1950 e 1990
•Diretores com mais de 3 filmes
JAVAEE7 Exercícios
•15. Escreva os seguintes queries em JPQL usando a Hierarquia 4:
•Nomes de todos os Participantes da etapa com origem: "Nova York" e
destino: "Moscow" que possuem ingresso com status = "Pago"
•16. Escreva os seguintes queries usando a Hierarquia 3:
•Valor total (para cada item: item.quantidade * produto.preco) de
cada pedido de status="finalizado" do cliente de userid=Fred
•Soma (sum) e média (avg) dos valores totais de todos os pedidos
JAVAEE7
JPA
javapersistenceapi
8
queriescriteria
JAVAEE7 Criteria
•Criteria é uma API do JPA que permite a construção de queries
dinâmicos e verificados em tempo de compilação, usando objetos
•Este query JPQL
select p from Produto p where p.preco < 50.0
•Pode ser expresso em Criteria da seguinte forma:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Produto> query =

cb.createQuery(Produto.class); // tipo do select
Root<Produto> raiz = query.from(Produto.class); // tipo do from
Predicate condicao = cb.lessThan(raiz.get("preco"), 50.0); // predicado
query.where(condicao); // adiciona a clausula where
query.select(raiz); // diz o que vai ser selecionado
JAVAEE7 Construção de um query
•Queries de Criteria são um grafo de objetos
•A raiz do grafo é encapsulado no CriteriaQuery
•Um query mínimo requer o uso de três classes do pacote
javax.persistence.criteria:
•CriteriaBuilder, que encapsula vários métodos para construir o query,
•CriteriaQuery, que representa a consulta
•Root que é raiz da consulta e representa os objetos selecionados pela
cláusula FROM
JAVAEE7 Construção de um query
•1) Criar um CriteriaQuery através da classe CriteriaBuilder:
CriteriaBuilder builder =

entityManagerFactory.getCriteriaBuilder();
•2) obter o objeto que irá encapsular o query:
CriteriaQuery<Produto> query = 

builder.createQuery( Produto.class );
•3) O objeto raiz do grafo é declarado através da interface Root, que constrói a
cláusula “from” do query. Isto é equivalente a fazer “from Produto p” em JPQL:
Root<Produto> p = query.from(Produto.class);
•4) Finalmente constrói-se a cláusula “select” do query usando o método select():
query.select(p);
•O query está pronto. Neste momento ele é equivalente ao string JPQL.
JAVAEE7 Execução de um Query
•Uma vez pronto, pode-se executar um Criteria Query da mesma
forma que um JPQL Query
•1) Passe o objeto query como parâmetro de um TypedQuery:
TypedQuery<Produto> query = 

em.createQuery(query);
•2) Chame um método de execução pára obter os resultados
List<Produto> resultado =

query.getResultList();
JAVAEE7 Consultas que retornam tuplas
•Consultas que retornam múltiplos objetos podem ser feitas com
from(), join() ou fetch() e métodos similares
•O query JPQL:
SELECT p1, p2 FROM Produto p1, Produto p2
•Pode ser escrito usando Criteria da seguinte forma:
CriteriaQuery<Tuple> criteria = cb.createQuery(Tuple.class);
Root<Produto> p1 = criteria.from(Produto.class);
Root<Produto> p2 = criteria.from(Produto.class);
criteria.multiselect(p1, p2);
JAVAEE7 Outer Join (Left Join)
•Um join como na query abaixo:
SELECT item, produto.nome 

FROM Item item 

LEFT OUTER JOIN item.produto produto
•Pode ser escrito em Criteria da seguinte forma:
CriteriaQuery<Tuple> criteria = cb.createQuery(Tuple.class);
Root<Item> item = criteria.from(Item.class);
Join<Item> produto = item.join("produto", JoinType.LEFT);
criteria.multiselect(item, produto.get("nome"));
JAVAEE7 Fetch Join
•A interface Join retornada pelo método join() é subinterface da interface
From, portanto pode ser usada em metódos que esperam um From
•Um join usando fetch como este em JPQL:
SELECT item 

FROM Item item 

JOIN FETCH item.produto
•Pode ser expresso em Criteria usando a seguinte sintaxe:
CriteriaQuery<Item> criteria = cb.createQuery(Item.class);
Root<Item> item = criteria.from(Item.class);
Fetch<Item, Produto> produto = item.fetch("produto");
criteria.select(item);
JAVAEE7 Interfaces Criteria
Expression<X>
TupleElement<X>
Selection<X>
Path<X>
From<Z,X>
Root<Z,X> Join<Z,X>
PluralJoin<Z, C, E>
CollectionJoin<Z, E>
SetJoin<Z, E>
ListJoin<Z, E>
MapJoin<Z, K,V>
Predicate<X>
SubQuery<X>
ParameterExpression<X>
JAVAEE7 Principais interfaces
•Expression – São construídas compondo outras expressões. Retornada em métodos de
CriteriaQuery e CriteriaBuilder (sum(), diff(), equal())
•Predicate – Conjunção (ou disjunção) das restrições de query representado por valor
booleano.A cláusula where recebe um Predicate. São construídos compondo outros
predicados. Retornado em métodos de CriteriaBuilder (equal(), and(), or(), between())
•Path – Representa caminho de navegação em um grafo. Ex: objeto.referencia.atributo.
O método get() de Root acessa atributos de objetos através de expressões de path.
•Join – Representa join para uma @Entity, objeto @Embeddable ou @Basic
•Selection – Qualquer item retornado em um resultado de query, como uma expressão
(Expression), subquery (SubQuery), predicado (Predicate), caminho (Path), etc.
•SubQuery – Representa um subquery
JAVAEE7 Métodos de CriteriaQuery e Subquery
•A hierarquia que representa um query em Criteria possui duas classes
•CriteriaQuery (query principal)
•Subquery

•Elas têm a superclasse AbstractQuery em comum e métodos que
representam cláusulas e outras partes de um query:
•Herdados de AbstractQuery (valem para queries principais e subqueries): 

distinct(), from(), groupBy(), having(), subQuery(), where()
•Definidos em CriteriaQuery (valem apenas para queries principais): 

multiselect(), select()
•Definidos em Subquery (valem apenas para subqueries): 

correlate(), getParent()
JAVAEE7 CriteriaBuilder
•A classe CriteriaBuilder possui métodos para a construção de
todas as expressões usadas nas cláusulas dos queries e subqueries
•Encapsuladas em instâncias de Expression ou subclasses
•Podem ser criadas chamando os factory methods de CriteriaBuilder
•Envolvem desde a criação de literais até condicionais, expressões
boleanas, de comparação, etc.
Expression<Integer> i1 = builder.literal(123);
Expression<Integer> i2 = builder.sum(3,4);
Predicate p1 = builder.and(true, false);
Predicate p2 = builder.not(p1);
JAVAEE7 Exemplos
•Encontre todos os produtos que são chips e cuja margem de lucro é positiva
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Produto> query = cb.createQuery(Produto.class);
Root<Produto> root = query.from(Produto.class);
Predicate igual = cb.equal(root.get("descricao"), "chip");
Expression<Double> subtracao = cb.diff(root.get("preco"),
root.get("custo"));
Predicate maiorQue = cb.greaterThan(subtracao, 0.0);
Predicate clausulaWhere = cb.and(igual, maiorQue);
query.where(clausulaWhere);
query.select(root);
TypedQuery<Produto> q = em.createQuery(query);
JAVAEE7 Exemplos
•Encontre todos os produtos cujo preço é pelo menos 1000 e no máximo 2000
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Produto> query = cb.createQuery(Produto.class);
Root<Produto> root = query.from(Produto.class);
Predicate between = cb.between(root.get("preco"),
1000.0, 2000.0);
query.where(between);
query.select(root);
JAVAEE7 Exemplos
•Encontre todos os produtos cujo fabricante é Sun ou Intel
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Produto> query = 

cb.createQuery(Produto.class);
Root<Produto> root = query.from(Produto.class);
query.where(root.get("fabricante").in("Intel", "Sun"));
query.select(root);
JAVAEE7 Exemplos
•Encontre todos os produtos com IDs que começam com 12 e
terminam em 3
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Produto> query = 

cb.createQuery(Produto.class);
Root<Produto> root = query.from(Produto.class);
query.where(cb.like(root.get("id"), "12%3"));
query.select(root);
JAVAEE7 Exemplos
•Encontre todos os produtos que têm descrições null
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Produto> query =

cb.createQuery(Produto.class);
Root<Produto> root = query.from(Produto.class);
query.where(cb.isNull(root.get("descricao")));
query.select(root);
JAVAEE7 Exemplos
•Encontre todos os pedidos que não têm itens (coleção)
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Pedido> query = 

cb.createQuery(Pedido.class);
Root<Pedido> root = query.from(Pedido.class);
query.where(cb.isEmpty(root.get("itens")));
query.select(root);
JAVAEE7 Exemplos
•Retorne os pedidos que contem um determinado item (passado
como parâmetro)
Item item = new Item(); // item a ser testado
// ...
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Pedido> query =

cb.createQuery(Pedido.class);
Root<Pedido> root = query.from(Pedido.class);
Predicate isMember =

cb.isMember(item, root.get("itens"));
query.where(isMember);
query.select(root);
JAVAEE7 Exemplos
•Encontre produtos com preços entre 1000 e 2000 ou que tenham código 1001
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Produto> query = 

cb.createQuery(Produto.class);
Root<Produto> root = query.from(Produto.class);
Predicate between = 

cb.between(root.get("preco"), 1000.0, 2000.0);
Predicate igual = 

cb.equal(root.get("codigo"), 1001);
query.where(cb.or(between, igual));
query.select(root);
JAVAEE7 Exemplos com relacionamentos
•Selecione todos os clientes com pedidos com total maior que 1000:
CriteriaBuilder cb = em.getCriteriaBuilder();

CriteriaQuery<Cliente> query = cb.createQuery(Cliente.class);

Root<Cliente> root = query.from(Cliente.class);

Path<Pedido> pedido = root.get("pedidos");

query.where(cb.greaterThan(pedido.get("total"), 1000.0));

query.select(root);
•Mesmo query usando um inner join explícito:
CriteriaBuilder cb = em.getCriteriaBuilder();

CriteriaQuery<Cliente> query = cb.createQuery(Cliente.class);

Root<Cliente> root = query.from(Cliente.class);

Join<Cliente, Pedido> pedido = root.join("pedidos");

query.where(cb.greaterThan(pedido.get("total"), 1000.0));

query.select(root);
JAVAEE7 Exemplos com relacionamentos
•Lances onde o item é de categoria que começa com “Celular” e teve lance > 1000:
CriteriaBuilder cb = em.getCriteriaBuilder();

CriteriaQuery<Lance> query = cb.createQuery(Lance.class); 

Root<Lance> root = query.from(Lance.class); 

query.where(cb.and(

cb.like(root.get("item").get("categoria").get("nome"), "Celular%"),

cb.greaterThan(root.get("item").get("lanceObtido").get("total")1000.0)));

query.select(root);
•Mesmo query usando vários inner joins explícitos:
CriteriaBuilder cb = em.getCriteriaBuilder();

CriteriaQuery<Lance> query = cb.createQuery(Lance.class); 

Root<Lance> root = query.from(Lance.class); 

Join<Lance, Item> item = root.join("item");

Join<Item, Categoria> cat = item.join("categoria");

Join<Item, Lance> vencedor = item.join("lanceObtido");

query.where(cb.and(cb.like(cat.get("nome"), "Celular%"),

cb.greaterThan(vencedor.get("total"), 1000.0)));

query.select(root);
JAVAEE7 Exemplos
•Encontre a média do total de todos os pedidos:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Double> query = 

cb.createQuery(Double.class); // avg retorna Double
Root<Pedido> root =

query.from(Pedido.class); // from Ingresso i
Expression<Double> media = cb.avg(root.get("total"));
query.select(media);
JAVAEE7 Exemplos
•Obtenha a soma dos preços de todos os produtos dos pedidos feitos
no bairro de Botafogo:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<BigDecimal> query = cb.createQuery(BigDecimal.class);
Root<Pedido> root = query.from(Pedido.class);
Join<Pedido, Item> item = root.join("itens");
Join<Pedido, Cliente> cliente = item.join("cliente");
Predicate where = cb.and(
cb.equal(cliente.get("bairro"), "Botafogo"),
cb.equal(cliente.get("cidade"), "Rio de Janeiro")
);
query.where(where);
Expression<BigDecimal> total = 

cb.sum(item.get("produto").get("preco"));
query.select(total);
JAVAEE7 Exemplos
•Obtenha a contagem de clientes agrupadas por bairro:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Object[]> query = 

cb.createQuery(Object[].class);
Root<Cliente> root = query.from(Cliente.class);
query.multiselect(root.get("bairro"), cb.count(root));
query.groupBy(root.get("bairro"));
TypedQuery<Object[]> q = em.createQuery(query);
...
JAVAEE7 Exemplos
•Obtenha o valor médio dos pedidos, agrupados por pontos, para
os clientes que têm entre 1000 e 2000 pontos:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Object[]> query = 

cb.createQuery(Object[].class);
Root<Pedido> root = query.from(Pedido.class);
query.multiselect(root.get("pontos"), 

cb.avg(root.get("total")));
Join<Pedido, Cliente> cliente = root.join("cliente");
query.groupBy(cliente.get("pontos"));
query.having(cb.between(cliente.get("pontos"), 

1000.0, 2000.0));
JAVAEE7 Exemplos com subqueries
•Obtenha os empregados que são casados com outros empregados:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Empregado> query = 

cb.createQuery(Empregado.class);
Root<Empregado> root = query.from(Empregado.class);
Subquery<Empregado> subquery = 

query.subquery(Empregado.class);
Root<Empregado> conjuge = 

subquery.from(Empregado.class);
subquery.where(cb.equal(conjuge.get("conjuge "), 

root.get("conjuge ")));
subquery.select(conjuge);
query.where(cb.exists(subquery));
query.select(root).distinct(true);
JAVAEE7 Exemplos com subqueries (All/Any)
•Retorne apenas os produtos cujo preço seja maior que o valor incluído
em todos os orçamentos:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Produto> query = cb.createQuery(Produto.class);
Root<Produto> root = query.from(Produto.class);
Subquery<Empregado> subquery = 

query.subquery(Empregado.class);
Root<Orcamento> orcamento = 

subquery.from(Orcamento.class);
subquery.where(cb.equal(orcamento.get("item ").get("codigo"), 

root.get("codigo")));
subquery.select(orcamento.get("item").get("preco"));
query.where(cb.greaterThan(root.get("preco"), 

cb.all(subquery)));
query.select(root);
JAVAEE7 Select com DataStransferObject
•O query usando select com construtor mostrado na seção anterior
com JPQL pode ser construído com Criteria da forma abaixo:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Lugares> query = 

cb.createQuery(DataTransferObject.class);
Root<Filme> root = query.from(Filme.class);
Join<Filme, Diretor> diretor = root.join("etapas");
query.where(cb.like(root.get("nome"), "%Allen"));
query.select(cb.construct(Lugares.class,

etapa.get("origem").get("nome"), 

etapa.get("destino").get("nome"))

);
JAVAEE7 Typesafe query
•É bem mais fácil encontrar erros em queries Criteria, comparados a JPQL, porque
o compilador ajuda na tarefa e detecta queries incorretos.
•Mas erros de digitação ainda podem acontecer já que a leitura dos campos das
entidades feita através de um get() recebe um String.
•Por exemplo, a linha abaixo para ler o campo “preco” não contém erros de
compilação:
Predicate condicao = qb.lt(raiz.get("prco"), 50.0);
•Mas se o string estiver errado, o query está incorreto: existem erros de sintaxe em
queries Criteria que também não são capturados em tempo de compilação!
JAVAEE7 Typesafe query
•A solução é o o typesafe query:
•O nome do atributo foi informado através de código Java, usando
um atributo estático e público da classe Produto_.
•Produto_.class é um metamodelo estático (static metamodel).
•Usando atributos através do metamodelo torna os queries typesafe
CriteriaBuilder qb = em.getCriteriaBuilder();
CriteriaQuery<Produto> cq = qb.createQuery(Produto.class);
Root<Produto> raiz = cq.from(Produto.class)
Predicate condicao = qb.lt(raiz.get(Produto_.preco), 50.0);
cq.where(condicao);
TypedQuery<Person> query = em.createQuery(cq);
JAVAEE7 Geração de metamodels
•Metamodelos precisam ser geradas. IDEs que suportam JPA 2 têm
ferramentas para gerá-los. Projetos Maven com EclipseLink podem
fazer a geração em uma das fases do POM.xml com um plug-in:
•O plugin precisa ser configurado e usará as classes declaradas no
persistence.xml para gerar metamodelos durante a fase de geração
de código do build (veja a documentação para mais detalhes)
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
<version>2.5.0</version>
</dependency>
JAVAEE7 Exercícios
•17. Implemente um dos queries do exercício 13 usando Criteria
•18. Implemente um dos queries do exercício 14 usando Criteria
•19. Implemente um dos queries do exercício 15 usando Criteria
•20. Implemente um dos queries do exercício 16 usando Criteria
•21. Implemente um bean que realize uma pesquisa dinâmica em
Livros, filtrando por autor, isbn e título. Crie um mecanismo que
permita construir um query dinâmico:
•Se nenhum campo estiver preenchido, a busca será feita sem filtros
•Se algum campo estiver preenchido, ele deve ser acrescentado na
cláusula where da pesquisa
JAVAEE7
JPA
javapersistenceapi
9
transações,cacheelocks
JAVAEE7 Transações em JPA
•Podem ser
•Distribuídas com 2-phase commit (JTA)
•Configuradas como um recurso local (RESOURCE_LOCAL)
•Apenas transações JTA são gerenciadas pelo container (CMT - Container-
Managed Transactions) para configurar suporte transacional de forma
transparente e declarativa
•Transações JTA também podem ser controladas programaticamente (BMT -
Bean-Managed Transactions) através da API da classe UserTransaction,
que pode ser injetada como resource em componentes Java EE
JAVAEE7 Resource Local
•Usada em ambientes Java SE ou onde não há suporte a transações distribuídas
•getTransaction() obtém contexto transacional para operações de persistência
•Transações são delimitadas pela chamada dos métodos begin() e commit()/rollback():
public class AlunoDAO {
private EntityManagerFactory emf;
AlunoDAO() { emf = Persistence.createEntityManagerFactory("escola-PU");}
public void addAluno(Aluno aluno) {
EntityManager em = emf.getEntityManager();
try
em.getTransaction().begin();
em.persist(aluno);
em.getTransaction().commit();
} catch(Exception e) {
em.rollback();
} finally { em.close(); }
}
}
<persistence-unit
name="escola-PU"

transaction-type="RESOURCE_LOCAL">
Em persistence.xml:
JAVAEE7 JTA (Java Transaction API)
•Disponível em servidores Java EE e suporta transações distribuídas (2-phase)
•Pode ser obtida e injetada como um @Resource em WebServlets, EJBs, e outros
componentes que rodam no container Java EE
•Em ambientes CDI também pode ser injetada com @Inject
public class AlunoDAOBean {
@PersistenceContext(unitName="escola-PU")
private EntityManager;
@Resource UserTransaction ut;
public void addAluno(Aluno aluno) {
try
ut.begin();
em.persist(aluno);
ut.commit();
} catch(Exception e) {
ut.rollback();
} finally { em.close(); }
}
}
<persistence-unit
name="escola-PU"

transaction-type="JTA">
Em persistence.xml:
JAVAEE7 CMT (JTA) em EJB
•Em EJB transações gerenciadas pelo container (CMT),JTA é o
comportamento default e é transparente
•Todos os métodos de um SessionBean são automaticamente
incluídos em um contexto transacional
@Stateless
public class AlunoSessionBean {
@PersistenceContext 

EntityManager em;
public void addAluno(Aluno aluno) {
em.persist(aluno);
}
}
<persistence-unit
name="escola-PU"

transaction-type="JTA">
Em persistence.xml:
JAVAEE7 CMT (JTA) em CDI
•Em CDI o mesmo comportamento pode ser obtido nos métodos
declarados como @Transactional
@Model
public class AlunoSessionBean {
@Inject

EntityManager em;
@Transactional
public void addAluno(Aluno aluno) {
em.persist(aluno);
}
} <persistence-unit
name="escola-PU"

transaction-type="JTA">
Em persistence.xml:
JAVAEE7 Cache
•O JPA possui dois níveis de cache
•O Contexto de Persistência, controlado pelo EntityManager (L1)
•Cache L2: Mecanismo compartilhado.
•Cache é um recurso de performance que deve ser usado com cuidado
•Há risco de resultar em inconsistência de dados
•Pode inclusive introduzir bugs
•O custo-benefício com os ganhos de performance poderá compensar o
esforço extra de gerenciar o cache
JAVAEE7 Cache L1 (contexto de persistência) e L2
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro
JPA Tutorial Intro

Mais conteúdo relacionado

Mais procurados (20)

Java básico - Módulo 05 - Estruturas de Repetição
Java  básico - Módulo 05 - Estruturas de RepetiçãoJava  básico - Módulo 05 - Estruturas de Repetição
Java básico - Módulo 05 - Estruturas de Repetição
 
Minicurso de JavaScript (Portuguese)
Minicurso de JavaScript (Portuguese)Minicurso de JavaScript (Portuguese)
Minicurso de JavaScript (Portuguese)
 
JSP: Introdução Parte 1
JSP: Introdução Parte 1JSP: Introdução Parte 1
JSP: Introdução Parte 1
 
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js + Expres...
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js +  Expres...Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js +  Expres...
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js + Expres...
 
Especificação de requisitos
Especificação de requisitosEspecificação de requisitos
Especificação de requisitos
 
Curso de Node JS Básico
Curso de Node JS BásicoCurso de Node JS Básico
Curso de Node JS Básico
 
Linguagem PHP
Linguagem PHPLinguagem PHP
Linguagem PHP
 
Mock objects - Teste de código com dependências
Mock objects - Teste de código com dependênciasMock objects - Teste de código com dependências
Mock objects - Teste de código com dependências
 
Spring Boot RestApi.pptx
Spring Boot RestApi.pptxSpring Boot RestApi.pptx
Spring Boot RestApi.pptx
 
Spring data jpa
Spring data jpaSpring data jpa
Spring data jpa
 
JAVA 8
JAVA 8JAVA 8
JAVA 8
 
Spring Data JPA
Spring Data JPASpring Data JPA
Spring Data JPA
 
Aula 1 - Introdução a POO
Aula 1 -  Introdução a POOAula 1 -  Introdução a POO
Aula 1 - Introdução a POO
 
Spring Framework - MVC
Spring Framework - MVCSpring Framework - MVC
Spring Framework - MVC
 
Introduction to Spring Framework
Introduction to Spring FrameworkIntroduction to Spring Framework
Introduction to Spring Framework
 
Hibernate
HibernateHibernate
Hibernate
 
Polimorfismo em java
Polimorfismo em javaPolimorfismo em java
Polimorfismo em java
 
Spring Core
Spring CoreSpring Core
Spring Core
 
Springboot Microservices
Springboot MicroservicesSpringboot Microservices
Springboot Microservices
 
Spring Boot Tutorial
Spring Boot TutorialSpring Boot Tutorial
Spring Boot Tutorial
 

Semelhante a JPA Tutorial Intro

TechDay - Sistemas WEB em Java - Rogério N. Jr.
TechDay - Sistemas WEB em Java - Rogério N. Jr.TechDay - Sistemas WEB em Java - Rogério N. Jr.
TechDay - Sistemas WEB em Java - Rogério N. Jr.Rogério Napoleão Jr.
 
Introdução ao JPA com Hibernate
Introdução ao JPA com HibernateIntrodução ao JPA com Hibernate
Introdução ao JPA com HibernateDanilo Braga
 
Introdução ao JPA com Hibernate
Introdução ao JPA com HibernateIntrodução ao JPA com Hibernate
Introdução ao JPA com HibernateDanilo Braga
 
Gerenciamento de projetos com o Apache Ant
Gerenciamento de projetos com o Apache AntGerenciamento de projetos com o Apache Ant
Gerenciamento de projetos com o Apache AntDenis L Presciliano
 
Gerenciamento de projetos com o Apache Ant
Gerenciamento de projetos com o Apache AntGerenciamento de projetos com o Apache Ant
Gerenciamento de projetos com o Apache AntDenis L Presciliano
 
Mini curso hibernate com anotações
Mini curso hibernate com anotaçõesMini curso hibernate com anotações
Mini curso hibernate com anotaçõesdieguinhomcz
 
Mini curso hibernate com anotações
Mini curso hibernate com anotaçõesMini curso hibernate com anotações
Mini curso hibernate com anotaçõesdieguinhomcz
 
Sistemas Distribuídos - Comunicação Distribuída - EJB
Sistemas Distribuídos - Comunicação Distribuída - EJBSistemas Distribuídos - Comunicação Distribuída - EJB
Sistemas Distribuídos - Comunicação Distribuída - EJBAdriano Teixeira de Souza
 
Processos iniciais do mapeamento OR
Processos iniciais do mapeamento ORProcessos iniciais do mapeamento OR
Processos iniciais do mapeamento ORNécio de Lima Veras
 
Uma abordagem ao Java EE 6
Uma abordagem ao Java EE 6Uma abordagem ao Java EE 6
Uma abordagem ao Java EE 6danielfcampos
 
Resumo Anotacoes Certificacao SCBCD 5
Resumo Anotacoes Certificacao SCBCD 5Resumo Anotacoes Certificacao SCBCD 5
Resumo Anotacoes Certificacao SCBCD 5Gilberto Holms
 
hibernate annotation
hibernate annotationhibernate annotation
hibernate annotationeduardo dias
 

Semelhante a JPA Tutorial Intro (20)

Hibernate conceitos
Hibernate conceitosHibernate conceitos
Hibernate conceitos
 
TechDay - Sistemas WEB em Java - Rogério N. Jr.
TechDay - Sistemas WEB em Java - Rogério N. Jr.TechDay - Sistemas WEB em Java - Rogério N. Jr.
TechDay - Sistemas WEB em Java - Rogério N. Jr.
 
Hibernate - Aula 01
Hibernate - Aula 01Hibernate - Aula 01
Hibernate - Aula 01
 
Introdução ao JPA com Hibernate
Introdução ao JPA com HibernateIntrodução ao JPA com Hibernate
Introdução ao JPA com Hibernate
 
Introdução ao JPA com Hibernate
Introdução ao JPA com HibernateIntrodução ao JPA com Hibernate
Introdução ao JPA com Hibernate
 
Tutorial JSF 2.0 (2012)
Tutorial JSF 2.0 (2012)Tutorial JSF 2.0 (2012)
Tutorial JSF 2.0 (2012)
 
Gerenciamento de projetos com o Apache Ant
Gerenciamento de projetos com o Apache AntGerenciamento de projetos com o Apache Ant
Gerenciamento de projetos com o Apache Ant
 
Gerenciamento de projetos com o Apache Ant
Gerenciamento de projetos com o Apache AntGerenciamento de projetos com o Apache Ant
Gerenciamento de projetos com o Apache Ant
 
Tag Libraries e JSTL
Tag Libraries e JSTLTag Libraries e JSTL
Tag Libraries e JSTL
 
JPA com Hibernate
JPA com HibernateJPA com Hibernate
JPA com Hibernate
 
Mini curso hibernate com anotações
Mini curso hibernate com anotaçõesMini curso hibernate com anotações
Mini curso hibernate com anotações
 
Mini curso hibernate com anotações
Mini curso hibernate com anotaçõesMini curso hibernate com anotações
Mini curso hibernate com anotações
 
Sistemas Distribuídos - Comunicação Distribuída - EJB
Sistemas Distribuídos - Comunicação Distribuída - EJBSistemas Distribuídos - Comunicação Distribuída - EJB
Sistemas Distribuídos - Comunicação Distribuída - EJB
 
Java Server Pages
Java Server PagesJava Server Pages
Java Server Pages
 
Processos iniciais do mapeamento OR
Processos iniciais do mapeamento ORProcessos iniciais do mapeamento OR
Processos iniciais do mapeamento OR
 
Hibernate
HibernateHibernate
Hibernate
 
Uma abordagem ao Java EE 6
Uma abordagem ao Java EE 6Uma abordagem ao Java EE 6
Uma abordagem ao Java EE 6
 
Apache Struts
Apache StrutsApache Struts
Apache Struts
 
Resumo Anotacoes Certificacao SCBCD 5
Resumo Anotacoes Certificacao SCBCD 5Resumo Anotacoes Certificacao SCBCD 5
Resumo Anotacoes Certificacao SCBCD 5
 
hibernate annotation
hibernate annotationhibernate annotation
hibernate annotation
 

Mais de Helder da Rocha

Como criar um mapa temático interativo com dados abertos e D3.js
Como criar um mapa temático interativo com dados abertos e D3.jsComo criar um mapa temático interativo com dados abertos e D3.js
Como criar um mapa temático interativo com dados abertos e D3.jsHelder da Rocha
 
Transforming public data into thematic maps (TDC2019 presentation)
Transforming public data into thematic maps (TDC2019 presentation)Transforming public data into thematic maps (TDC2019 presentation)
Transforming public data into thematic maps (TDC2019 presentation)Helder da Rocha
 
TDC 2019: transformando 
dados
públicos
em mapas interativos
TDC 2019: transformando 
dados
públicos
em mapas interativosTDC 2019: transformando 
dados
públicos
em mapas interativos
TDC 2019: transformando 
dados
públicos
em mapas interativosHelder da Rocha
 
Padrões essenciais de mensageria para integração de sistemas
Padrões essenciais de mensageria para integração de sistemasPadrões essenciais de mensageria para integração de sistemas
Padrões essenciais de mensageria para integração de sistemasHelder da Rocha
 
Visualização de dados e a Web
Visualização de dados e a WebVisualização de dados e a Web
Visualização de dados e a WebHelder da Rocha
 
Eletrônica Criativa: criando circuitos com materiais alternativos
Eletrônica Criativa: criando circuitos com materiais alternativosEletrônica Criativa: criando circuitos com materiais alternativos
Eletrônica Criativa: criando circuitos com materiais alternativosHelder da Rocha
 
Introdução à Visualização de Dados (2015)
Introdução à Visualização de Dados (2015)Introdução à Visualização de Dados (2015)
Introdução à Visualização de Dados (2015)Helder da Rocha
 
Introdução a JPA (2010)
Introdução a JPA (2010)Introdução a JPA (2010)
Introdução a JPA (2010)Helder da Rocha
 
Minicurso de Segurança em Java EE 7
Minicurso de Segurança em Java EE 7Minicurso de Segurança em Java EE 7
Minicurso de Segurança em Java EE 7Helder da Rocha
 
Atualização Java 8 (2014)
Atualização Java 8 (2014)Atualização Java 8 (2014)
Atualização Java 8 (2014)Helder da Rocha
 
Curso de Java: Introdução a lambda e Streams
Curso de Java: Introdução a lambda e StreamsCurso de Java: Introdução a lambda e Streams
Curso de Java: Introdução a lambda e StreamsHelder da Rocha
 
Threads 07: Sincronizadores
Threads 07: SincronizadoresThreads 07: Sincronizadores
Threads 07: SincronizadoresHelder da Rocha
 
Threads 08: Executores e Futures
Threads 08: Executores e FuturesThreads 08: Executores e Futures
Threads 08: Executores e FuturesHelder da Rocha
 
Threads 06: Coleções concorrentes
Threads 06: Coleções concorrentesThreads 06: Coleções concorrentes
Threads 06: Coleções concorrentesHelder da Rocha
 
Threads 05: Travas de Exclusão Mútua
Threads 05: Travas de Exclusão MútuaThreads 05: Travas de Exclusão Mútua
Threads 05: Travas de Exclusão MútuaHelder da Rocha
 
Threads 04 Variáveis atômicas
Threads 04 Variáveis atômicasThreads 04 Variáveis atômicas
Threads 04 Variáveis atômicasHelder da Rocha
 
Threads 03: Ciclo de vida, aplicações e boas práticas
Threads 03: Ciclo de vida, aplicações e boas práticasThreads 03: Ciclo de vida, aplicações e boas práticas
Threads 03: Ciclo de vida, aplicações e boas práticasHelder da Rocha
 

Mais de Helder da Rocha (20)

Como criar um mapa temático interativo com dados abertos e D3.js
Como criar um mapa temático interativo com dados abertos e D3.jsComo criar um mapa temático interativo com dados abertos e D3.js
Como criar um mapa temático interativo com dados abertos e D3.js
 
Transforming public data into thematic maps (TDC2019 presentation)
Transforming public data into thematic maps (TDC2019 presentation)Transforming public data into thematic maps (TDC2019 presentation)
Transforming public data into thematic maps (TDC2019 presentation)
 
TDC 2019: transformando 
dados
públicos
em mapas interativos
TDC 2019: transformando 
dados
públicos
em mapas interativosTDC 2019: transformando 
dados
públicos
em mapas interativos
TDC 2019: transformando 
dados
públicos
em mapas interativos
 
Padrões essenciais de mensageria para integração de sistemas
Padrões essenciais de mensageria para integração de sistemasPadrões essenciais de mensageria para integração de sistemas
Padrões essenciais de mensageria para integração de sistemas
 
Visualização de dados e a Web
Visualização de dados e a WebVisualização de dados e a Web
Visualização de dados e a Web
 
Eletrônica Criativa: criando circuitos com materiais alternativos
Eletrônica Criativa: criando circuitos com materiais alternativosEletrônica Criativa: criando circuitos com materiais alternativos
Eletrônica Criativa: criando circuitos com materiais alternativos
 
Introdução à Visualização de Dados (2015)
Introdução à Visualização de Dados (2015)Introdução à Visualização de Dados (2015)
Introdução à Visualização de Dados (2015)
 
Java 9, 10, 11
Java 9, 10, 11Java 9, 10, 11
Java 9, 10, 11
 
Introdução a JPA (2010)
Introdução a JPA (2010)Introdução a JPA (2010)
Introdução a JPA (2010)
 
Minicurso de Segurança em Java EE 7
Minicurso de Segurança em Java EE 7Minicurso de Segurança em Java EE 7
Minicurso de Segurança em Java EE 7
 
Curso de Java: Threads
Curso de Java: ThreadsCurso de Java: Threads
Curso de Java: Threads
 
Atualização Java 8 (2014)
Atualização Java 8 (2014)Atualização Java 8 (2014)
Atualização Java 8 (2014)
 
Curso de Java: Introdução a lambda e Streams
Curso de Java: Introdução a lambda e StreamsCurso de Java: Introdução a lambda e Streams
Curso de Java: Introdução a lambda e Streams
 
Threads 07: Sincronizadores
Threads 07: SincronizadoresThreads 07: Sincronizadores
Threads 07: Sincronizadores
 
Threads 09: Paralelismo
Threads 09: ParalelismoThreads 09: Paralelismo
Threads 09: Paralelismo
 
Threads 08: Executores e Futures
Threads 08: Executores e FuturesThreads 08: Executores e Futures
Threads 08: Executores e Futures
 
Threads 06: Coleções concorrentes
Threads 06: Coleções concorrentesThreads 06: Coleções concorrentes
Threads 06: Coleções concorrentes
 
Threads 05: Travas de Exclusão Mútua
Threads 05: Travas de Exclusão MútuaThreads 05: Travas de Exclusão Mútua
Threads 05: Travas de Exclusão Mútua
 
Threads 04 Variáveis atômicas
Threads 04 Variáveis atômicasThreads 04 Variáveis atômicas
Threads 04 Variáveis atômicas
 
Threads 03: Ciclo de vida, aplicações e boas práticas
Threads 03: Ciclo de vida, aplicações e boas práticasThreads 03: Ciclo de vida, aplicações e boas práticas
Threads 03: Ciclo de vida, aplicações e boas práticas
 

JPA Tutorial Intro

  • 1. JAVAEE7 JPA javapersistenceapi Helder da Rocha (helder@acm.org) Atualizado em setembro de 2016
  • 2. JAVAEE7 Sobre este tutorial Este é um tutorial sobre tecnologia JPA (de acordo com a especificação Java EE 7) criado para cursos presenciais e práticos de programação por Helder da Rocha. Este curso aborda os conhecimentos essenciais para usar JPA na prática usando Hibernate ou EclipseLink como provedor (consulte a documentação oficial para detalhes). Este material poderá ser usado de acordo com os termos da licença Creative Commons BY- SA (Attribution-ShareAlike) descrita em http://creativecommons.org/licenses/by-sa/3.0/br/ legalcode. O código dos exemplos está disponível em repositório público no GitHub e é software livre sob os termos da licença Apache 2.0.
  • 3. JAVAEE7 Conteúdo 1. Introdução 2. Configuração do ambiente 3. Persistência 4. Mapeamento de entidades 5. Mapeamento de relacionamentos 6. Mapeamento de herança 7. Queries JPQL 8. Queries Criteria 9.Tuning: transações, cache e locks
  • 5. JAVAEE7 O que é JPA? •Java Persistence API: especificação Java EE que define um mapeamento entre uma estrutura relacional e um modelo de objetos em Java •Pode ser também usado de forma standalone, em aplicações Java SE, utilizando um provedor de persistência independente •Java EE 7 adota a especificação JPA 2.1 (JSR 338). •JPA permite a criação de entidades persistentes - objetos gerenciados que retém seu estado além do tempo em que estão na memória •Oferece uma camada de persistência (CRUD de objetos) e um mecanismo de mapeamento objeto-relacional (ORM) declarativo.
  • 6. JAVAEE7 Object-Relational Mapping (ORM) •Tempo de configuração • Classes mapeadas a tabelas (esquemas) •Tempo de execução • Instâncias (objetos) automaticamente sincronizadas com registros conta correntista saldo 1 Gargantua 1370 2 Pantagruel 3450 3 Gargamel 800 4 Morticia 8200 Classe Conta String codigo String nome double saldo instância:Conta codigo="4" nome="Morticia" saldo=8200 Tabela Conta Banco de Dados Relacional
  • 7. JAVAEE7 Camada de persistência •JPA oferece uma API para interagir com objetos persistentes mapeados através de ORM •AAPI é proporcionada pela interface EntityManager e contém •Métodos para gravar objetos em meio persistente (persist), remover (remove) e atualizar (update) •Métodos para construir e processar consultas usando scripts (JPA Query Language) ou objetos (Criteria) •Métodos para configurar o comportamento do cache de objetos (que cuida da sincronização do estado de objetos e transações)
  • 8. JAVAEE7 Configuração de JPA •Para configurar JPA em uma aplicação é necessário que essa aplicação tenha acesso, através do seu Classpath, aos seguintes componentes: •Módulo contendo a API do JPA (as classes, interfaces, métodos, anotações do pacote javax.persistence) •Um provedor de persistência JPA (ex: Hibernate, EclipseLink) que implementa as interfaces da API •Drivers necessários para configuração do acesso aos datasources usados (e pools de conexão, se houver) •Um arquivo persistence.xml para configurar a camada de persistência.
  • 9. JAVAEE7 Unidade de persistência •O contexto de persistência, usado para sincronizar as instâncias persistentes com o banco de dados é chamado de Entity Manager •Controla o ciclo de vida das instâncias •Pode ser instanciado pela própria aplicação (em aplicações standalone), obtido via JNDI ou injeção de dependências (padrão em Java EE) •O conjunto de entity managers e as entidades que eles gerenciam configura uma unidade de persistência (Persistence Unit). •Declarada no arquivo persistence.xml •Referenciada em classes que usam objetos persistentes (DAOs, fachadas, beans, servlets)
  • 10. JAVAEE7 persistence.xml mínimo •Deve estar no Classpath acessível pelas classes Java usadas na aplicação em 
 /META-INF/persistence.xml, e possui a seguinte configuração mínima: •Este exemplo é utilizável em servidor Java EE que tenha sido configurado para oferecer um datasource default (java:comp/DefaultDataSource). •Normalmente aplicações usam datasources selecionadas de forma explícita. <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence 
 http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="MyPU" transaction-type="JTA"> </persistence-unit> </persistence>
  • 11. JAVAEE7 DataSource com JTA •Este persistence.xml típico de uma aplicação JPA simples rodando em um servidor Java EE 7 declara o nome da unidade de persistência e: •o modelo de transações utilizada (JTA – gerenciada pelo container), •o nome JNDI de um datasource específico (previamente configurado) •uma única entidade mapeada •uma única propriedade de configuração específica do provedor usado <persistence version="2.1" …> <persistence-unit name="com.empresa.biblioteca.PU" transaction-type="JTA"> <jta-data-source>jdbc/Biblioteca</jta-data-source> <class>br.empresa.biblioteca.entity.Livro</class> <properties> <property name="eclipselink.deploy-on-startup" value="true" /> </properties> </persistence-unit> </persistence> Os detalhes de conexão com o banco de dados precisam ser configurados no servidor de aplicações
  • 12. JAVAEE7 EclipseLink e PostgreSQL •Exemplo de persistence.xml usado para acessar mesmos dados via camada de persistência configurada localmente (transações gerenciadas pela aplicação), usando provedor EclipseLink e banco PostgreSQL <persistence version="2.1" … > <persistence-unit name="com.empresa.biblioteca.PU" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>br.empresa.biblioteca.entity.Livro</class> <properties> <property name="javax.persistence.jdbc.driver" 
 value="org.postgresql.Driver" /> <property name="javax.persistence.jdbc.url" 
 value="jdbc:postgresql://localhost:5432/postgres" /> <property name="javax.persistence.jdbc.user" value="postgres" /> <property name="javax.persistence.jdbc.password" value="admin" /> </properties> </persistence-unit> </persistence>
  • 13. JAVAEE7 Hibernate e MySQL •Este persistence.xml configura unidade de persistência com transações locais e provedor Hibernate acessando localmente um banco de dados MySQL <persistence … >
 <persistence-unit name="LojaVirtual" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>lojavirtual.Produto</class> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/> <property name="hibernate.connection.username" value="root"/> <property name="hibernate.connection.password" value=""/> <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/test"/> </properties> </persistence-unit> </persistence>
  • 14. JAVAEE7 Entidades e mapeamento •A arquitetura do JPA baseia-se no mapeamento de tabelas a classes, colunas a atributos •O objetivo do mapeamento é construir uma hierarquia de entidades •Entidade (Entity) é um objeto persistente. Em JPA é um JavaBean (POJO) mapeado a uma tabela •Uma entidade JPA pode ser mapeada a uma tabela de duas formas: •Através de elementos XML no arquivo orm.xml •Através de anotações em classes, métodos, atributos, construtores
  • 15. JAVAEE7 Mapeamento em orm.xml •Os únicos tags obrigatórios são <entity> e <id>, e os atributos name. Pode-se ter mais detalhamento (ex: tipos, constraints) ou menos (ex: omitir tags com nomes de tabela e colunas, se forem iguais). <entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" 
 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm 
 http://xmlns.jcp.org/xml/ns/persistence/orm/orm_2_1.xsd" version="2.1"> <entity name="Livro" class="br.com.argonavis.Livro" access="FIELD"> <table name="LIVRO"/> <attributes> <id name="id"> <column name="ID"/> <generated-value strategy="TABLE" generator="LIVRO_SEQ"/> </id> <basic name="titulo"> <column name="TITULO"/> </basic> <basic name="paginas"> <column name="PAGINAS"/> </basic> </attributes> </entity> </entity-mappings> Se existir, deve estar localizado em META-INF/orm.xml
  • 16. JAVAEE7 Mapeamento com anotações •Para declarar uma entidade com anotações JPA é necessário no mínimo anotar a classe com @Entity e anotar pelo menos um atributo (ou método) com @Id, indicando sua chave primária •Atributos expostos via getters/setters são mapeados por default a colunas de mesmo nome @Entity public class Livro implements Serializable { @Id private Long id; private String titulo; private int paginas; public Long getId() { return id;} public void setId(Long id) { this.id = id;} public String getTitulo() { return this.titulo;} public void setTitulo(String titulo) { this.titulo = titulo;} public int getPaginas() { return this.paginas;} public void setPaginas(int paginas) { this.paginas = paginas;} } É preciso também determinar como o Id será atribuído (se gerado pelo banco ou fornecido)
  • 17. JAVAEE7 Mapeamento com anotações •Pode-se mudar os defaults e realizar configurações adicionais é usando anotações como @Table, @Column, @CollectionTable, @JoinTable, @JoinColumn, etc. @Entity @Table(name="BOOK") public class Livro implements Serializable { @Id private Long id; @Column(name="TITLE") private String titulo; @Column(name="PAGES") private int paginas; … }
  • 18. JAVAEE7 Exercícios: configuração •Configuração do ambiente para realizar os exercícios •Pode ser necessário adaptar os exercícios ao ambiente usado (banco de dados, provedor de persistência, IDE, ambiente Java EE ou standalone, duração do treinamento) •Alguns exercícios usam arquivos disponíveis no repositório GitHub •Scripts SQL 99 e aplicações JDBC em Java podem ser usados para criar tabelas usadas em exercícios (é necessário configurá-los) •As hierarquias de classes e diagramas de entidades a seguir poderão ser usados nos exercícios (que irão fazer referência a eles)
  • 19. JAVAEE7 Exercícios: Hierarquia e SQL 1 CREATE TABLE Livro( id INTEGER PRIMARY KEY, isbn VARCHAR(13) UNIQUE, titulo VARCHAR(256), idioma CHAR(2) ) Livro id: int titulo: String isbn: String idioma: String
  • 20. JAVAEE7 Exercícios: Hierarquia e SQL 2 Movie id: int title: String imdb: String director: Director year: int duration: int Director id: int name: String CREATE TABLE Diretor ( id INTEGER PRIMARY KEY, nome VARCHAR(256), ) CREATE TABLE Filme ( id INTEGER PRIMARY KEY, imdb CHAR(9) NOT NULL, titulo VARCHAR(256), diretor INTEGER, ano INTEGER, duracao INTEGER, constraint fk_diretor foreign key (diretor) references Diretor(id) ) *
  • 21. JAVAEE7 Exercícios: Hierarquia 3 1 1..* 1 1 * PK FK Cliente nome email pedidos cartao Usuario id senha userid Produto id nome preco Pedido id cliente status Item id pedido produto quantidade Operador codigo versao
  • 22. JAVAEE7 Exercícios: SQL 1 create table produtos ( produto_id integer primary key, nome_prod varchar(64), preco numeric(10,2), ); create table usuarios ( usuario_id varchar(8) primary key, senha varchar(16), userid varchar(16) ); create table clientes ( cliente_id varchar(8) primary key, nome varchar(512), email varchar(256), usuario_fk integer, cartao varchar(16), constraint fk_usuario foreign key (usuario_fk) references usuarios(usuario_id) );
  • 23. JAVAEE7 Exercícios: SQL 2 create table operadores ( operador_id varchar(8) primary key, codigo varchar(8), versao integer, usuario_fk integer, constraint fk_usuario foreign key (usuario_fk) references usuarios(usuario_id) ); create table pedidos ( pedido_id integer primary key, cliente_fk integer, status varchar(16), constraint fk_cliente foreign key (cliente_fk) references clientes(cliente_id) ); create table itens ( item_id integer primary key, pedido_fk integer, produto_fk integer, qte integer, constraint fk_pedido foreign key (pedido_fk) references pedidos(pedido_id), constraint fk_produto foreign key (produto_fk) references produtos(produto_id) );
  • 24. JAVAEE7 Exercícios: Hierarquia 4 Corrida Etapa Participante Ingressoingresso participante Localidade participantes etapas origem destino valor status nome nome nome nome * * 1 1 1 * etapas 1 1
  • 25. JAVAEE7 Exercícios:
 Hierarquia 5 Livro id: int titulo: String isbn: String idioma: String Autor id: int nome: String Editora id: int nome: String Assunto id: AssuntoPK descricao: String Exemplar id: int disponivel: boolean ExemplarEletronico id: int tamanho: long ExemplarImpresso id: int paginas: int Usuario id: int nome: String emprestimos usuario livro assunto editora autores obras titulos contexto assuntos 10 0..1 * 1 * * 1 * 1 * 1 *
  • 27. JAVAEE7 Configuração standalone •Usada em projetos Java EE para rodar testes de integração com o banco ou em aplicações JPA standalone •É preciso incluir explicitamente no Classpath os JARs da API, do provedor JPA e driver do banco de dados (e pool de conexões se houver) <dependencies> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>javax.persistence</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>eclipselink</artifactId> <version>2.5.0</version> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>9.4.1208</version> <scope>runtime</scope> </dependency> </dependencies> Configuração das dependências Maven para para acesso JPA usando EclipseLink 2.5 e banco de dados PostgreSQL
  • 28. JAVAEE7 Configuração standalone •Como as transações serão controladas pela aplicação e serão locais, a unidade de persistência declara o tipo de transações como RESOURCE_LOCAL: <persistence version="2.1"…> <persistence-unit name="tutorial-jpa" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>br.com.argonavis.javaee7.jpa.intro.Livro</class> <properties> … <property name="eclipselink.ddl-generation" 
 value="drop-and-create-tables" /> </properties> </persistence-unit> </persistence> Entidade a ser configurada Configuração do EclipseLink para gerar tabelas automaticamente (o Hibernate suporta uma equivalente)
  • 29. JAVAEE7 Criação do EntityManager (standalone) •A fábrica que cria o EntityManager pode ser obtida via consulta JNDI global a um servidor (se houver container cliente configurado), ou criada localmente com um objeto Persistence. import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; public class LivroTest { @Test public void testPersist() throws Exception { EntityManagerFactory factory = 
 Persistence.createEntityManagerFactory("tutorial-jpa"); EntityManager em = factory.createEntityManager(); ... em.close(); } } Criação local do EntityManager Configuração para usar a unidade de persistência declarada no persistence.xml
  • 30. JAVAEE7 Criação da entidade •A entidade a ser sincronizada com a tabela é instanciada e configurada normalmente em Java puro public class LivroTest { @Test public void testPersist() throws Exception { ... Livro livro = new Livro(); livro.setTitulo("Meu Livro"); livro.setPaginas(100); ... } }
  • 31. JAVAEE7 Uso da persistência (standalone) •Padrão básico: obter o contexto de persistência (createEntityManager) seguido do contexto transacional (begin), realizar as operações envolvendo persistência, e fechar o contexto transacional (commit se sucesso ou rollback se falha, fechando o contexto de persistência (close) no final da operação. public class LivroTest { @Test public void testPersist() throws Exception { ... try { em.getTransaction().begin(); em.persist(livro); // cria um registro novo no commit() em.getTransaction().commit(); } catch (Exception e) { em.getTransaction().rollback(); } finally { em.close(); } } } // detalhes do teste (asserts) omitidos É preciso obter o contexto transacional do EntityManager: persist() precisa ser chamada dentro de um contexto transacional
  • 32. JAVAEE7 Configuração em Java EE •Em Java EE o suporte a JPA é nativo, e o acesso ao banco de dados deve ocorrer através de um datasource previamente configurado no servidor, acessível dentro de um contexto JTA <dependencies> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>7.0</version> <scope>provided</scope> </dependency> ... </dependencies> Dependências em um projeto Maven não são incluídas no componente (JAR): o driver do banco, pool e provedor JPA fazem parte do servidor
  • 33. JAVAEE7 Configuração em Java EE •O arquivo persistence.xml declara estratégia transacional JTA (gerenciada pelo container) e em vez de dados para acesso ao banco, informa o caminho JNDI para o datasource correspondente <persistence version="2.1" …> <persistence-unit name="tutorial-jpa" transaction-type="JTA"> <jta-data-source>jdbc/TutorialJPA</jta-data-source> <class>br.com.argonavis.javaee7.jpa.intro.ejb.Livro</class> </persistence-unit> </persistence>
  • 34. JAVAEE7 Acesso via WebServlet •Em Java EE o EntityManager poderá ser obtido via JNDI injeção de dependências com de @PersistenceContext (ou via CDI, se previamente configurado) @WebServlet("/Livro") public class LivroTestServlet extends HttpServlet { @PersistenceContext(unitName="tutorial-jpa")
 EntityManager em; @Resource 
 UserTransaction ut; protected void doGet(HttpServletRequest rq, HttpServletResponse rs) 
 throws ServletException, IOException { Writer out = rs.getWriter(); try { ut.begin(); List<Livro> livros = em.createQuery("select livro from Livro livro").getResultList(); for(Livro livro : livros) out.write("<p>"+livro.getTitulo()+ "</p>"); ut.commit(); } catch (…) {…} // rollback e finalização } UserTransaction é necessário para delimitar o contexto transacional
  • 35. JAVAEE7 @Stateless
 public class LivroDAOSessionBean { @PersistenceContext
 EntityManager em; public Livro findByID(Long id) { Query query = em.createNamedQuery("selectById"); query.setParameter("id", id); return (Livro)query.getSingleResult(); } public List<Livro> findAll() { return (List<Livro>)em.createNamedQuery("selectAll")
 .getResultList(); } public void delete(Livro livro) { em.remove(livro); } public void update(Livro livro) { em.merge(livro); } public Livro insert(Livro livro) { return em.merge(livro); } } Acesso via EJB Se houver apenas uma unidade de persistência, o nome dela não precisa ser informado Os métodos de um Session Bean são transacionais por default. Haverá rollback se houver exceção
  • 36. JAVAEE7 Named queries •Um @NamedQuery contém JPQL associado a um nome que pode ser usado pelos clientes para obter referência a um query: •Exemplo: @Entity @NamedQueries({ @NamedQuery(name="selectAll", query="SELECT livro FROM Livro livro"), @NamedQuery(name="selectById", query="SELECT livro FROM Livro livro WHERE livro.id=:id") }) public class Livro { ... } TypedQuery<Livro> query = 
 em.createNamedQuery("selectById", Livro.class);
  • 37. JAVAEE7 Acesso via CDI •Métodos não são transacionais por default. O contexto transacional pode ser obtido de duas formas: •UserTransaction (como no WebServlet) •Anotação @Transactional (comportamento igual ao EJB) @Named public class LivroDAOManagedBean { @Inject EntityManager em; public Livro findByID(Long id) { TypedQuery<Livro> query = 
 em.createNamedQuery("selectById", Livro.class); query.setParameter("id", id); return query.getSingleResult(); } public List<Livro> findAll() { return em.createNamedQuery("selectAll", Livro.class)
 .getResultList(); } @Transactional public void delete(Livro livro) { em.remove(livro); } @Transactional public void update(Livro livro) { em.merge(livro); } @Transactional public Livro insert(Livro livro) { return em.merge(livro); } }
  • 38. JAVAEE7 Passo-a-passo JPA: configuração •Crie um projeto (Maven, Eclipse, NetBeans, etc) •Configure dependências necessárias para compilar JPA (e executar se standalone) •Configure um banco de dados no seu projeto (se standalone) ou no servidor de aplicações (se Java EE) e use as propriedades para configurar o persistence.xml •Inclua dados de configuração em META-INF/persistence.xml definindo um nome para a unidade de persistência, e tipo RESOURCE_LOCAL, se standalone, e JTA, se Java EE <persistence version="2.1" ... > <persistence-unit name="biblioteca-PU" transaction-type="JTA"> <jta-data-source>jdbc/sample</jta-data-source> <class>biblioteca.Livro</class> <properties> <property name="javax.persistence.schema-generation.database.action"
 value="drop-and-create"/> </properties> </persistence-unit> </persistence> Use para gerar as tabelas automaticamente Entidade mapeada
  • 39. JAVAEE7 Passo-a-passo JPA: mapeamento •Crie um POJO (classe Java com atributos privativos acessíveis via getters e setters) •Declare @Entity, @Id e uma estratégia de geração do ID (depende do banco de dados) •Inclua uma referência à entidade no persistence.xml (veja slide anterior) @Entity public class Livro { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; private String titulo; private String isbn; private String idioma; public int getId() {return id;} public void setId(int id) {this.id = id;} public String getTitulo() {return titulo;} ... } Gera ID automaticamente (depende do banco usado)
  • 40. JAVAEE7 Passo-a-passo JPA: persistência •Crie um cliente Java. Em Java EE use um WebServlet, ManagedBean (exemplo abaixo) ou Session Bean •Obtenha uma referência para o EntityManager da unidade de persistência •Chame os métodos de EntityManager dentro de contexto transacional (automático em Session Beans) @Named @RequestScoped public class LivroBean { @PersistenceContext(unitName="biblioteca-PU") EntityManager em; @Override @Transactional public Collection<Livro> getLivros() { String query = "select livro from Livro livro"; return em.createQuery(query, Livro.class).getResultList(); } @Override @Transactional public int insert(Livro livro) { em.persist(livro); return em.merge(livro).getId(); } ... <h:dataTable value="#{livroBean.livros}" 
 var="livro"> <h:column>#{livro.isbn}</h:column> <h:column>#{livro.titulo}</h:column> <h:column>#{livro.idioma}</h:column> Cliente para o ManagedBean
  • 41. JAVAEE7 Exercícios •1. Configure seu ambiente para usar JPA (persistence.xml) •a.Ambiente standalone: carregue as dependências necessárias no ClassPath, configure um banco de dados e um provedor •b.Ambiente Java EE: configure um datasource JTA no servidor de aplicações e um provedor de persistência •2. Construa a entidade da Hierarquia 1 (classe Livro) •Não crie uma tabela em SQL: configure para que as tabelas do banco sejam geradas automaticamente) e chame métodos para inserir e selecionar objetos •Depois de configurado, rode a classe PopulateLivros para preencher a tabela com dados que possam ser pesquisados
  • 43. JAVAEE7 Operações CRUD •Create, Retrieve, Update, Delete (Criar, Recuperar,Atualizar, Remover) são as principais tarefas da camada de persistência •Podem envolver uma entidade ou uma rede de entidades interligadas através de relacionamentos •JPA oferece várias maneiras de realizar operações CRUD: •Métodos de persistência transitiva: persist, merge, delete, find •Java Persistence Query Language (JPQL) •API Criteria •SQL nativo
  • 44. JAVAEE7 Retrieve com JPQL •A obtenção de uma entidade, o “R” de “Retrieve” do acrônimo CRUD, pode ser feita conhecendo-se sua chave primária através de find: Livro livro = em.find(Livro.class, 1234); •Outra alternativa é realizar uma consulta pesquisando o estado da entidade com JPQL através de um Query (ou TypedQuery): TypedQuery query = 
 em.createQuery("select m from Livro m where m.id=:id", Livro.class); query.setParameter("id", 1234); Livro livro = query.getSingleResult();
  • 45. JAVAEE7 Retrieve com Criteria •Criteria é um query construído dinamicamente via relacionamentos entre objetos. É ideal para pesquisas que são construídas em tempo de execução: •Para usar a API desta forma, a classe Livro_class foi gerada automaticamente (veja: Criteria Metamodel API) pelas ferramentas da IDE (plug-in Maven) CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<Livro> criteria = builder.createQuery(Livro.class); Root<Livro> queryRoot = criteria.from(Livro.class); criteria.where(builder.equal(queryRoot.get(Livro_.id), 1234)); TypedQuery<Livro> q = em.createQuery(criteria); Livro livro = q.getSingleResult();
  • 46. JAVAEE7 Create-Update-Delete com find e JPQL •Operações que envolvem atualização, “Create”, “Update” e “Delete”, geralmente são executadas através de métodos de persistência transitiva persist, merge e delete •A mesma alteração também pode ser realizada via JPQL: Query query = em.createQuery("UPDATE Livro m" + "SET m.titulo = :titulo WHERE m.id = :id"); query.setParameter("titulo", "Novo título"); query.setParameter("id", "1234"); query.executeUpdate(); Livro livro = em.find(Livro.class, 1234); livro.setTitulo("Novo título"); em.merge(livro);
  • 47. JAVAEE7 Create-Update-Delete com Criteria •As mesmas operações podem ser realizadas com a API Criteria CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaUpdate updateCriteria =
 builder.createCriteriaUpdate(Livro.class); Root<Livro> updateRoot = 
 updateCriteria.from(Livro.class); updateCriteria.where(builder.equal(updateRoot.get(Livro_.id), 
 "1234")); updateCriteria.set(updateRoot.get(Livro_.titulo), 
 "Novo título"); Query q = em.createQuery(updateCriteria); q.executeUpdate();
  • 48. JAVAEE7 Operações de persistência •Uma entidade pode estar em quatro estados durante seu ciclo de vida •transiente (new) - @Id = null •persistente (managed) - @Id != null e sincronizado com tabela •desligado (detached) - @Id != null e não sincronizado (pode estar obsoleto) •removido (removed) - @Id != null mas registro inexistente na tabela •O estado determina o comportamento do objeto quando são chamadas operações de persistência transitiva sobre ele •Entidade nova (transiente) ainda não inserida no banco tem ID null •Quando a entidade torna-se persistente ela recebe um ID. Uma vez atribuído um ID a uma entidade, esse valor não muda mais
  • 49. JAVAEE7 Ciclo de vida e operações de persistência
  • 50. JAVAEE7 Controle da persistência •void persist(objeto) – Gera SQL INSERT e transforma o objeto em uma entidade persistente. Causa EntityExistsException se o ID já existir no banco. •Object merge(objeto) – Gera SQL UPDATE ou INSERT e devolve a entidade construída. O INSERT será gerado se o ID do objeto for null. Caso contrário, o ID será chave primária para realizar UPDATE. Causa IllegalArgumentException se ID não for null e não existir no banco. •void remove(objeto) – Remove o registro do banco, desligando a entidade permanentemente. •void detach(objeto) – Separa a instancia do seu registro tornando a entidade desligada (detached). Ocorre em entidades usadas fora do contexto transacional. Um merge() ou refresh() dentro do contexto transacional religa a entidade tornando-a persistente. •void refresh(objeto) – Sincroniza a entidade com dados obtidos do banco, sobrepondo alterações que tenham sido feitas no estado do objeto. •void flush() – Sincroniza as entidades do contexto de persistência (oposto de refresh).
  • 51. JAVAEE7 Estados da Persistência Transiente Desligado Persistente Pessoa nome = Yoda id = 0 Pessoa id nome Pessoa nome = Yoda id = 1 Pessoa id nome 1 Yoda Pessoa nome = Jabba id = 1 Pessoa id nome 1 Jabba Pessoa nome = Jabba id = 1 Pessoa id nome 1 Jabba Pessoa nome = Luke id = 1 Pessoa id nome 1 Jabba Classes Tabelas Atualização não foi sincronizada no banco
  • 52. JAVAEE7 Callbacks •@PostLoad - executado depois que uma entidade foi carregada no contexto de persistência atual (ou refresh) •@PrePersist - executado antes da operação persist ser executada (ou cascade - sincronizado com persist se entidade for sincronizada via merge) •@PostPersist - executado depois que entidade foi persistida (inclusive via cascade) •@PreUpdate - antes de operação UPDATE •@PostUpdate - depois de operação UPDATE •@PreRemove - antes de uma operação de remoção
  • 53. JAVAEE7 EntityListener •Para declarar callbacks em uma classe separada, pode-se usar a anotação @EntityListener na entidade informando o nome da classe que os contém: •Neste caso, os métodos devem receber a entidade como parâmetro: @Entity @EntityListeners(LivroListener.class) public class Livro implements Serializable { … } public class LivroListener { @PostLoad public void livroLoaded(Livro livro) { ... } ... }
  • 54. JAVAEE7 Exercícios •3. Escreva um cliente JPA simples para •a) Inserir uma lista de livros no banco de dados (converta o código de PopulateLivros.java para JPA) •b) Listar os livros •c) Alterar um dos livros (trocar o título) •d) Remover um dos livros •e) Recuperar um dos livros pela chave primária •f) Listar a coleção de objetos resultante •4. Execute a classe PopulateFilmes.java (que cria a Hierarquia 2) e escreva um cliente que liste todos os filmes e diretores
  • 56. JAVAEE7 Mapeamento de entidades •Uma classe que representa uma entidade • deve ser anotada com @Entity (ou declarada como <entity> no deployment descriptor orm.xml) • deve ter um campo @Id (a menos que participe como subclasse de uma hierarquia mapeada em JPA) • se não usar os valores default, deve declarar mapeamentos explícitos para tabelas e colunas (@Table, @Column, @JoinColumn) •Deve ter um construtor sem argumentos e não pode ser interface ou um enum ou classe final, nem ter variáveis de instância ou métodos finais
  • 57. JAVAEE7 Mapeamento de entidades •Suportam herança, associações polimórficas, queries polimórficos • Podem estender classes comuns e vice-versa • Somente entidades podem ser usadas em queries JPA •O estado persistente é representado pelas variáveis de instância • Acessadas via propriedades (getters/setters) • Por default, variáveis de instância não declaradas transient e que não tenham a anotação @Transient são consideradas persistentes
  • 58. JAVAEE7 Mapeamento de entidades •Assinaturas válidas para propriedades: • Propriedades escalares (value-types) ou lado unitário de associações com entidades (@Column):
 T getProperty() e void setProperty(T t) • Coleções de escalares (value-types) ou lado múltiplo de associações com entidades (@JoinColumn)
 Set<T> getProperty() e void setProperty(Set<T>) •Tipos permitidos: • Value-types: primitivos, String, BigInteger, BigDecimal, Date, Calendar,Time, Timestamp, byte[], Byte[], char, Character[], enums e coleções desses valores • Tipos serializáveis e coleções de tipos serializáveis • Entidades e coleções de entidades
  • 59. JAVAEE7 Mapeamento com defaults @Entity public class Cliente implements Serializable { @Id private Long id; private String nome; private Endereco endereco; @OneToMany private Set<Pedido> pedidos = new HashSet(); @ManyToMany private Set<Pagamento> formasPagamento = new HashSet(); public Cliente() {} public Long getId() { return id; } public void setId(Long id) { this.id = id; } ... public Collection<Order> getPedidos() { return pedidos; } public void setPedidos(Collection<Pedido> pedidos) { this.pedidos = pedidos; } public Set<Pagamento> getFormasPagamento() { return formasPagamento; } ... } Usando o mínimo de anotações! Anotações ausentes (ex: @Column, @Table, etc.) resultam em comportamento default (ex: tabela com mesmo nome que classe) Anotações também possuem propriedades configuráveis; 
 se omitidas, são usadas as default
  • 60. JAVAEE7 Mapeamento detalhado @Entity @Table(name="CLIENTES", schema="loja") public class Cliente implements Serializable { @Id @GeneratedValue(strategy=SEQUENCE, generator="CLI_SEQ") @Column(name="CUST_ID") private Long id; @Basic @Column(name="NOME_CL", nullable=false, length=512) private String nome; @Basic @Column(name="END_CL", nullable=false, length=512) private Endereco endereco; @OneToMany(Cascade={CascadeType.ALL}, mappedBy="cliente", fetch=FetchType.EAGER) @JoinColumn(name="CLIENTE_ID", nullable=false) private Set<Pedido> pedidos = new HashSet(); @ManyToMany(mappedBy="clientes") @OrderBy("valor ASC") @JoinTable(name="CLIENTES_PAGAMENTOS", joinColumns= @JoinColumn(name="CLIENTE_ID", referencedColumnName="ID"), inverseJoinColumns= @JoinColumn(name="PAG_ID", referencedColumnName="ID")) private Set<Pagamento> formasPagamento = new HashSet(); ... } Anotações detalhando forma como entidade é mapeada às tabelas, e selecionando configurações default para gravação e recuperação de objetos
  • 61. JAVAEE7 •5. Configure um mapeamento entre a tabela Livro e a classe Livro •6. Configure um mapeamento entre a classe Movie e a tabela Filme Exercícios CREATE TABLE Livro( id INTEGER PRIMARY KEY, isbn VARCHAR(13) UNIQUE, titulo VARCHAR(256), idioma CHAR(2) ) CREATE TABLE Filme ( id INTEGER PRIMARY KEY, imdb CHAR(9) NOT NULL, titulo VARCHAR(256), diretor VARCHAR(64), ano INTEGER, duracao INTEGER ) Livro id: int titulo: String isbn: String idioma: String Movie id: int title: String imdb: String director: Director year: int duration: int
  • 63. JAVAEE7 Relacionamentos entre entidades •Para mapear relacionamentos,JPA usa informações da estrutura do código Java e anotações mínimas (serão usados defaults onde possível) •A cardinalidade define o número de entidades em cada lado. Podem ser mapeados “muitos” e “um” resultando em quatro possibilidades: •Um para muitos •Muitos para um •Um para um •Muitos para muitos. •As duas primeiras são equivalentes, portanto há três associações: •@ManyToOne / @OneToMany •@OneToOne •@ManyToMany
  • 64. JAVAEE7 @ManyToOne unidirecional @Entity public class Produto { @Id @GeneratedValue int codigo; String nome; double preco; public int getCodigo() { return codigo; } public void setCodigo(int codigo) { this.codigo = codigo; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } ... @Entity public class Item { @ManyToOne private Produto produto; public Produto getProduto() { return produto; } public void setProduto(Produto produto) { this.produto = produto; } public double subtotal() { return produto.getPreco() * quantidade; } ... Classe Produto não sabe da existência da associação* Método de negócio que utiliza-se da associação para realizar uma operação * Essas anotações são insuficientes para a geração automática do esquema (as tabelas devem existir antes)
  • 65. JAVAEE7 Associações bidirecionais •Se as anotações @OneToOne, @ManyToMany e @ManyToOne forem usadas em associações bidirecionais é necessário especificar anotações de ambos os lados e utilizar o atributo mappedBy para informar o atributo da outra classe que faz a associação •O diagrama abaixo ilustra algumas associações bidirecionais. @OneToOne 
 CPF cpf; @OneToOne(mappedBy="cpf") 
 Cliente cliente; @ManyToMany
 Set<Turma> turmas; @ManyToMany(mappedBy="turmas") 
 Set<Aluno> alunos; @ManyToOne 
 Item item; @OneToMany(mappedBy="item")
 Set<Produto> produtos;
  • 66. JAVAEE7 @ManyToOne bidirecional @Entity public class Pedido { @OneToMany(mappedBy="pedido") private Set<Item> itens = new HashSet<Item>(); public Set<Item> getItens() { return itens; } public void setItens(Set<Item> itens) { this.itens = itens; } public void addItem(Item item) { itens.add(item); item.setPedido(this); } public double subtotal() { double subtotal = 0; for (Item item : itens) { subtotal += item.subtotal(); } return subtotal; } ... @Entity public class Item { @ManyToOne private Pedido pedido; public Pedido getPedido() { return pedido; } public void setPedido(Pedido pedido) { this.pedido = pedido; } public double subtotal() { ... } ... Utilitário para facilitar a adição de itens na associação (atualiza os dois lados da associação) Método de negócio que utiliza-se da associação para realizar uma operação
  • 67. JAVAEE7 @ManyToMany bidirecional @Entity public class Aluno { @Id @GeneratedValue private int id; @ManyToMany(mappedBy="alunos") private Set<Turma> turmas; public Set<Turma> getTurmas() { return turmas; } public void setTurmas(Set<Turma> turmas) { this.turmas = turmas; } public void matricular(Turma turma) { turmas.add(turma); if(!turmas.contains(turma)) turma.addAluno(this); } ... } @Entity public class Turma { @Id @GeneratedValue private int id; @ManyToMany(mappedBy="turmas") private Set<Aluno> alunos; public Set<Aluno> getAlunos() { return alunos; } public void setAlunos(Set<Turma> turmas) { this.alunos = alunos; } public void addAluno(Aluno aluno) { alunos.add(aluno); if(!alunos.contains(aluno)) aluno.matricular(this); } ... } Métodos utilitários para adicionar alunos e turmas
  • 68. JAVAEE7 Relacionamentos um-para-um •Objetos em um relacionamento com alto grau de dependência. No modelo relacional isto pode ser implementado de três maneiras: •Dois objetos, uma única tabela (dados em colunas da mesma tabela) •Um objeto, duas tabelas (dados em colunas de outra tabela) •Dois objetos, duas tabelas unidas por associação •Em JPA, a terceira estratégia pode ser implementada usando @ManyToOne (unidirecional com @UniqueConstraint) ou mais facilmente usando @OneToOne (via chave estrangeira ou primária). •As duas primeiras estratégias não são relacionamentos entre entidades, mas associações com instâncias ou coleções. Em JPA, a primeira é implementada usando @Embeddable e a segunda com @SecondaryTable.
  • 69. JAVAEE7 @OneToOne bidirecional @Entity public class Cliente { @OneToOne(mappedBy="cliente") private CPF cpf; public CPF getCPF() { return cpf; } public void setCPF(CPF cpf) { this.cpf = cpf; } ... @Entity public class CPF { @OneToOne private Cliente cliente; public Cliente getCliente() { return cliente; } public void setCliente(Cliente cliente) { this.cliente = cliente; } ... Só é necessário informar o mappedBy em um dos lados da associação
  • 70. JAVAEE7 Tipos das Coleções: List ou Set •Relacionamentos @ManyToOne e @ManyToMany envolvem coleções que normalmente são declarados como Set ou List •O mapeamento natural para registros em uma tabela é java.util.Set, porque Sets não possuem uma ordem especifica e não podem ser duplicados •Sets podem ser ordenados no query usando @OrderBy e na instância usando uma implementação ordenada como TreeSet •Pode-se usar List quando o índice é importante ou para compatibilidade com outros componentes (ex: componentes Primefaces que esperam List)
  • 71. JAVAEE7 Mapas •E possível mapear uma coleção a um mapa usando @MapKey e representando a coleção como um java.util.Map. •Um Map contem um Set de chaves e uma Collection de valores, e é indicado situações nas quais é mais eficiente recuperar um objeto através de uma chave. •A chave default é a chave-primária dos objetos da coleção: @Entity public class LojaVirtual { ... @OneToMany(mappedBy="lojaVirtual") @MapKey // indexado pela chave primaria public Map<Long, Cliente> clientes = new HashMap <>(); ... }
  • 72. JAVAEE7 Mapas •Usando o atributo name é possível indexar por outras propriedades dos objetos da coleção: •O mapeamento da chave também pode ser feito através das colunas, em vez dos atributos, usando @MapKeyColumn e @MapKeyJoinColumn. •Existem ainda mais duas anotações para @MapKey •@MapKeyEnumerated, se a chave for uma enumeração •@MapKeyTemporal, se a chave for uma data ou Timestamp. @Entity public class LojaVirtual { ... @OneToMany(mappedBy="lojaVirtual") @MapKey(name="cpf") // indexado pelo CPF public Map<String, Cliente> clientes = new HashMap<>(); ... } Veja mais detalhes na documentação
  • 73. JAVAEE7 Componentes @Embeddable •Entidades são objetos persistentes que têm identidade no banco •Objetos que contém dados persistentes mas não têm identidade unívoca no banco são identificados pelo seu estado, ou valor (value objects). •Em JPA são anotados como @Embeddable •No modelo de domínio representam um objeto independente, mas no modelo relacional são apenas algumas colunas de uma tabela. •São componentes da entidade que possui a tabela e declarados como atributos anotados como @Embedded •Muitas associações 1-1 podem ser implementadas de maneira mais eficiente como objetos embutidos.
  • 74. JAVAEE7 Componentes @Embeddable Cliente nome email cartao Endereco Rua CEP Cidade enderecoEntrega enderecoCobranca nome email cartao ent_rua ent_cep ent_cidade cob_rua cob_cep cob_cidade :Ciente enderecoEntrega:Endereco enderecoCobranca:Endereco <<Entidade>> <<Componente>> @Entity @Embeddable @Embedded •Uma única tabela contém dados dos objetos Cliente e Endereco •Endereco é um componente de Cliente, e declarado como @Embeddable •Um Cliente tem dois Enderecos e cada associação é declarada como @Embedded
  • 75. JAVAEE7 Componentes @Embeddable @Entity @Table(name="CLIENTE") public class Cliente { @Id @GeneratedValue(strategy=GenerationType.AUTO) private Long codigo; private String nome; ... @Embedded private Endereco enderecoCobranca; @Embedded @AttributeOverrides({ @AttributeOverride(name="rua", column=@Column(name="ENT_RUA")), @AttributeOverride(name="cep", column=@Column(name="ENT_CEP")), @AttributeOverride(name="cidade", column=@Column(name="ENT_CIDADE")), }) private Endereco enderecoEntrega; ... @Embeddable public class Endereco { @Column(name="COB_RUA") private String rua; @Column(name="COB_CEP") private String cep; @Column(name="COB_CIDADE") private String cidade; ... } reusa mesma classe Endereco, mas redefine mapeamentos
  • 76. JAVAEE7 @Embeddable collections •Se uma entidade contém uma coleção de componentes embutidos, ou tipos básicos (que não são entidades) deve ser anotado com @ElementCollection •A entidade abaixo contém uma coleção de objetos Endereco, que são @Embeddable, e uma coleção de Strings: @Entity public class Representantes { ... @ElementCollection private Set<Endereco> enderecos = new HashSet<>(); @ElementCollection private Set<String> emails = new HashSet<>(); ... }
  • 77. JAVAEE7 Chaves compostas •@Embeddable pode ser usado na criação de chaves compostas. Por exemplo, uma chave-primária que consiste de dois campos do tipo String: •Ela pode ser usada em uma entidade anotada com @EmbeddedId: •É responsabilidade da aplicação gerenciar o estado da chave composta, para que a persistência transitiva ocorra corretamente. @Entity @Table(name = "DEPENDENCIA") public class Dependencia { @EmbeddedId private DependenciaId id; // ... } @Embeddable public class DependenciaId { @Column(name = "APP_ID") private String appID; @Column(name = "GROUP_ID") private String groupID; //... }
  • 78. JAVAEE7 Mapeamento de enumerações •Enumerações podem ser persistidas se marcadas com @Enumerated public enum Regiao {
 NORTE, NORDESTE, SUL, SUDESTE, CENTRO_OESTE;
 } •Exemplo: @Entity
 public class SalaDeCinema { ...
 @Enumerated(EnumType.STRING)
 private Regiao regiao; •O EnumType default é ORDINAL: grava número no registro da tabela. STRING é não é afetado pela ordem das constantes (grava texto na tabela).
  • 79. JAVAEE7 Mapeamento de uma classe a duas tabelas •Usa-se @SecondaryTable para construir uma entidade que obtém seus dados de duas tabelas. •No exemplo abaixo a entidade Usuario está mapeado a uma tabela principal (USUARIOS) e uma tabela secundária (IMAGENS)
  • 80. JAVAEE7 Mapeamento de uma classe a duas tabelas •@Table é a tabela principal e @SecondaryTable a tabela secundária, que indica coluna(s) contendo a chave primária usada(s) para realizar a junção. •@PrimaryKeyJoinColumn contém: chave primária da tabela principal, chave referenciada na tabela secundária (ou apenas o primeiro se forem iguais). O atributo da segunda tabela informa a tabela e coluna a ser mapeada @Entity @Table(name="USUARIOS") @SecondaryTable(name="IMAGENS", pkJoinColumns = @PrimaryKeyJoinColumn(name="USUARIO_ID", referencedColumnName="IMG_ID")) public class Usuario implements Serializable { ... @Id Column(name="USUARIO_ID") private Long userId; @Column(table="IMAGENS", name="URL_IMG", nullable=true) private String avatar; ...
  • 81. JAVAEE7 Transitividade da persistência •Relacionamentos em JPA são implementados em Java puro, e não são gerenciados pelo container por default.Alterações precisam ser sincronizadas: Pedido p = new Pedido();
 Item i = new Item();
 p.addItem(i); // atualizando o pedido
 item.setPedido(p); // atualizando o item (se bidirecional) •As entidades precisam ser persistentes.Tentar adicionar uma entidade transiente a uma entidade persistente causa TransientObjectException. •persist() ou merge() dentro de um contexto transacional resolve o problema: em.persist(p);
 em.persist(i);
  • 82. JAVAEE7 Transitividade da persistência •Pode-se configurar persistência transitiva no JPA usando o atributo cascade das anotações de relacionamentos. •Para propagar a inserção de entidades use CascadeType.PERSIST: @OneToMany(cascade={CascadeType.PERSIST}, 
 mappedBy="item" )
 private Set<Item> itens = new HashSet<Item>(); •Quando um Pedido for persistido no banco, itens que estiverem na hierarquia de objetos também serão persistidos automaticamente.
  • 83. JAVAEE7 CascadeType •O atributo cascade recebe um array de opções CascadeType •PERSIST – propaga operações persist() e merge() em objetos novos •MERGE – propaga operações merge() •REMOVE – propaga operações remove() •DETACH – propaga operações detach() •REFRESH – propaga operações refresh() •ALL – propaga todas as operações. Declarar cascade=ALL é o mesmo que declarar cascade={PERSIST, MERGE, REMOVE, REFRESH, DETACH} •Um uso típico é PERSIST + MERGE, que garante inserts e updates transitivos @OneToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE}) •Se a remoção de um Pedido exigir a remoção de seus Itens um REMOVE é necessário. Pode-se usar ALL para que todas as operações sejam transitivas
  • 84. JAVAEE7 Lazy loading •Lazy loading um padrão de design usado para adiar a inicialização de um objeto para quando ele for realmente necessário •ORMs usam estratégias de lazy loading para otimizar pesquisas •Contribui para a eficiência da aplicação se usado corretamente •Um query, por default, retorna uma coleção de proxies para seus elementos (e não a coleção preenchida pelos próprios elementos) •Se um cliente fora do contexto transacional tentar acessar um elemento da coleção, haverá uma exceção de inicialização lazy. O comportamento default depende do provedor usado •Hibernate lança LazyInitializationException. •EclipseLink captura a exceção e abre nova conexão ao banco para obter os dados
  • 85. JAVAEE7 Configuração de lazy loading •É possível controlar o lazy loading configurando a recuperação default como eager (ansiosa), em vez de lazy (preguiçosa) de duas maneiras: •Através de mapeamento (estabelece um default para todas as situações) •Através de instruções no query (a cada consulta) •O atributo fetch=FetchType das anotações de relacionamentos configura o modo eager como default para todas as operações @OneToMany(mappedBy="pedido", fetch=FetchType.EAGER)
 private Set<Item> itens = new HashSet<Item>(); •No query, um fetch join devolve a coleção com todos os seus elementos select p from Pedido p join fetch p.itens
  • 86. JAVAEE7 Exercícios •7. Implemente o mapeamento Movie-Director da Hierarquia 2 •8. Implemente os mapeamentos de Cliente-Pedido-Item-Produto na Hierarquia 3 •9. Implemente todos os mapeamentos da Hierarquia 4 •Use @Embedded para o relacionamento Etapa-Localidade •Use @OneToOne para o relacionamento Participante-Ingresso •Implemente uma enumeração para guardar o status do ingresso com as constantes PAGO e NAO_PAGO •O relacionamento Corrida-Etapa é unidirecional •10. Implemente o relacionamento Assunto-Assunto na Hierarquia 35
  • 88. JAVAEE7 Mapeamento de herança •Entidades são objetos e suportam herança de classes, associações e queries polimórficos. Podem ser abstratas ou concretas, e podem ser subclasses ou superclasses de classes que não são entidades. •Mas não existe herança em tabelas. Herança é o descasamento mais visível entre os mundos relacional e orientado a objetos. •O mundo OO possui relacionamento “é um” e “tem um”, enquanto que o mundo relacional apenas possui relacionamento “tem um”. •Há três estratégias para lidar com esse problema (sugeridas por Scott Ambler, 2002). Essas estratégias são adotadas na arquitetura do JPA.
  • 89. JAVAEE7 MappedSuperclass •Entidades podem ter superclasses que não são entidades •Se a superclasse possuir a anotação @MappedSuperclass, seus atributos serão herdados e farão parte do estado persistente das subclasses •Uma @MappedSuperclass também pode incluir anotações de persistência nos seus atributos, mas não é uma entidade e não pode ser usada com operações de EntityManager ou Query (não está mapeada a uma tabela) •Apenas as subclasses de entidades concretas são mapeadas a tabelas e podem conter colunas correspondentes aos atributos herdados. @MappedSuperclass public class Quantia { @Id protected Long id; protected BigDecimal valor; ... } @Entity public class Pagamento extends Quantia { ... } @Entity public class Divida extends Quantia { ... }
  • 90. JAVAEE7 @Inheritance e InheritanceType •A anotação javax.persistence.Inheritance é usada para configurar o mapeamento de herança entre entidades em JPA •Elas implementam as três estratégias citadas que são selecionadas através das constantes da enumeração InheritanceType: public enum InheritanceType { 
 SINGLE_TABLE,
 JOINED,
 TABLE_PER_CLASS 
 }; •A estratégia default é SINGLE_TABLE, que mapeia todas as classes de uma hierarquia a uma única tabela no banco de dados •Há muitas possibilidades de configuração (mostraremos as mais simples)
  • 91. JAVAEE7 Tabela por Classe Concreta: TABLE_PER_CLASS Pagamento id valor Credito numero validade <<Entidade>> Debito banco conta <<Entidade>> @Id declarado apenas na superclasse @Entity @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) public abstract class Pagamento { @Id @GeneratedValue private long id; } @Entity public class Debito extends Pagamento {...} ID NUMERO VALIDADE 5 ID BANCO CONTA 5 CREDITO DEBITO <<Entidade>>
  • 92. JAVAEE7 Tabela por Classe Concreta: TABLE_PER_CLASS •Tem como vantagem o mapeamento direto entre classe e tabela normalizada. •A gravação é realizada via classe concreta, mas a pesquisa pode ser polimórfica, via classe abstrata e com resultado que inclui as subclasses concretas •Ex: filtrar Pagamentos por valor, sem precisar saber se Crédito ou Débito: select p from Pagamento p where p.valor > 1000 •A desvantagem dessa estratégia é a complexidade e ineficiência dos queries gerados. Exemplo de SQL gerado no Hibernate: select ID, VALOR, NUMERO, VALIDADE, BANCO, CONTA from (
 select ID, VALOR, NUMERO, VALIDADE, 
 null as BANCO, null as CONTA from CREDITO 
 union select ID, VALOR, null as NUMERO, null as VALIDADE, 
 BANCO, CONTA from DEBITO) where VALOR > 1000
  • 93. JAVAEE7 Tabela por hierarquia: SINGLE_TABLE @Entity @Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name="TIPO") public abstract class Pagamento { @Id @GeneratedValue private long id; } ID TIPO VALOR NUMERO VALIDADE BANCO CONTA 5 crd 100.0 23459403 12/15 null null 6 deb 100.0 null null 1234-5 993423-3 PAGAMENTO Coluna (@DiscriminatorColumn) presente na tabela mas sem mapeamento na classe @Entity @DiscriminatorValue("deb") public class Debito extends Pagamento {...} Pagamento id valor Credito numero validade <<Entidade>> Debito banco conta <<Entidade>> <<Entidade>>
  • 94. JAVAEE7 Tabela por hierarquia: SINGLE_TABLE •Mapeia uma hierarquia de classes inteira a uma tabela •A tabela precisa ter colunas para todas as propriedades de todas as classes. •A vantagem são pesquisas polimórficas mais eficientes, já que tudo acontece em uma única tabela. Este é o SQL conceitual para um query polimórfico: select ID, VALOR, BANCO, CONTA, NUMERO, VALIDADE 
 from PAGAMENTO 
 where VALOR > 1000 •Em query na classe concreta, o provedor de persistência poderá gerar este SQL: select ID, VALOR, BANCO, CONTA, NUMERO, VALIDADE 
 from PAGAMENTO 
 where TIPO = 'deb' and VALOR > 1000 •A principal desvantagem dessa estratégia é que as tabelas não são normalizadas
  • 95. JAVAEE7 Tabela por subclasse: JOINED @Entity @Inheritance(strategy=InheritanceType.JOINED) public abstract class Pagamento { @Id @GeneratedValue private long id; } Pagamento id valor Credito id numero validade ID NUMERO VALIDADE 5 <<Entidade>> Debito id banco conta <<Entidade>> ID BANCO CONTA 5 CREDITO DEBITO @Entity public class Debito extends Pagamento {...} ID VALOR 5 PAGAMENTO ID é PK e FK (default) <<Entidade>>
  • 96. JAVAEE7 Tabela por subclasse: JOINED •Uma Classe abstrata ou concreta = Uma Tabela distinta; relacionamento através de equivalência de chave primária e estrangeira (default) •Modelo relacional normalizado •Evolução sem efeitos colaterais: novas classes e tabelas podem ser criadas sem afetar existentes •Aplicação de restrições de integridade mais simples •Performance da pesquisa polimórfica ainda é baixa em hierarquias complexas (usa dados de todas as tabelas envolvidas) •Os provedores de persistência* geralmente geram SQL com outer join para pesquisas polimórficas e inner join para pesquisas em classes concretas *Hibernate e EclipseLink
  • 97. JAVAEE7 Qual estratégia? Há necessidade de consultas polimórficas? Hierarquia de classes é pequena? Tabela por Hierarquia InheritanceType.SINGLE_TABLE Tabela por Subclasse InheritanceType.JOINED Tabela por Classe Concreta InheritanceType.TABLE_PER_CLASS Tabelas tem que ser normalizadas? NÃO* * Se houver suporte no provedor (o suporte é opcional) SIM SIM NÃO NÃO SIM (default)
  • 98. JAVAEE7 Exercícios •11. Implemente um mapeamento da hierarquia Usuario- Operador-Cliente (Hierarquia 3) usando qualquer uma das três estratégias •12. Implemente uma mapeamento da hierarquia Exemplar- Exemplar Eletrônico-Exemplar Impresso (Hierarquia 5) usando uma estratégia diferente
  • 100. JAVAEE7 Consultas (queries) •Consultas podem ser construídas para recuperar entidades a partir de critérios baseados em seu conteúdo •JPA possui duas estratégias nativas: •JPQL – linguagem similar a SQL baseada em comandos de texto •Criteria – API usada para construir consultas usando objetos. •JPQL é geralmente mais fácil de aprender, mas Criteria permite a criação de queries com maior potencial de reuso e evolução, além de ser recomendada para queries dinâmicas
  • 101. JAVAEE7 Cláusulas •Consultas em bases de objetos têm princípios similares a consultas em bancos de dados •A cláusula mais importante é FROM, que declara o escopo da pesquisa. Na API Criteria é representada por um objeto raiz. •A clausula SELECT indica o que está sendo selecionado dentro do escopo FROM. Em JPA pode-se selecionar entidades, seus atributos, e resultados de operações realizados sobre elas •A cláusula opcional WHERE declara filtros que restringem os resultados da pesquisa. Sem WHERE todos os elementos do escopo declarado em FROM serão recuperados
  • 102. JAVAEE7 Joins •Operação que amplia o domínio da função para incluir objetos de um relacionamento usadas em JPQL e Criteria •Consultas que navegam no grafo de objetos usando o operador ponto (ex: cliente.pedido.item) escondem joins implícitos •Joins em grafos de objetos são similares mas não idênticos a joins no mundo relacional. Há três tipos em JPA. : •Lazy Inner Joins (default – joins implícitos são sempre inner joins) •Lazy Outer (ou Left) Joins •Eager (ou Fetch) Joins (que podem ser inner ou outer)
  • 103. JAVAEE7 Inner Joins e Outer joins •Inner Joins consideram apenas resultados que contém o relacionamento •Elementos que não possuem o relacionamento declarado são filtrados •Exemplo: uma consulta sobre objetos Cliente para obter o total de Pedidos (relacionamento Cliente-Pedido) •Um inner join não retorna os clientes que não têm pedidos. •Um outer join retorna tudo, mesmo que o cliente seja null
  • 104. JAVAEE7 Lazy Joins e Eager Joins •A inicialização dos elementos de uma coleção é Lazy por default •Uma coleção obtida em uma consulta pode conter apenas um proxy para cada elemento (é preciso fazer novas consultas para obter cada um) •O comportamento exato é dependente do contexto transacional e também do provedor de persistência utilizado •Eager Joins garantem que a coleção seja inicializada antes do uso •Depois da consulta a coleção está povoada com todos os seus elementos •Isto pode ser pré-configurado no mapeamento, mas é mais eficiente poder selecionar esse comportamento durante a consulta
  • 105. JAVAEE7 JPQL (JPA Query Language) •Linguagem de recuperação de dados •Similar a linguagens de query de objetos (HQL, EJB-QL, etc.) que a precederam •Parece com SQL mas opera sobre objetos e não tabelas •Consultas são objetos da classe Query/TypedQuery e podem ser construídas através de métodos de EntityManager •As instruções do query podem ser passadas diretamente para o método createQuery() como parâmetro do tipo String. @PersistenceContext EntityManager em; ... TypedQuery query = em.createQuery("SELECT p FROM Produto p", Produto.class);
  • 106. JAVAEE7 Named queries •O query pode também ser declarado previamente em anotações @NamedQuery em cada entidade: •Associado a um identificador, referenciado em createNamedQuery() @Entity @NamedQueries({ @NamedQuery(name="selectAllProdutos", query="SELECT p FROM Produto p") }) public class Produto implements Serializable { ... } TypedQuery query = em.createNamedQuery("selectAllProdutos", Produto.class);
  • 107. JAVAEE7 Consultas parametrizadas •Os parâmetros podem ser declarados em JPQL usando identificadores numéricos ou nomes precedidos por “:”: •Se houver parâmetros, eles podem ser preenchidos através de um ou mais métodos setParameter() antes de executar o query. TypedQuery query = 
 em.createQuery("SELECT p FROM Produto p WHERE p.preco > :maximo", 
 Produto.class); query.setParameter("máximo", 1000);
  • 108. JAVAEE7 Métodos que executam queries •Retornam resultados •Se o resultado for uma coleção, pode-se usar getResultList(): •Se retornar apenas um item (por exemplo, se o produto for selecionado por ID ou um campo unívoco), pode-se usar getSingleResult(): •Há outros métodos de execução não fazem pesquisa mas são usados para remoção ou atualização, como executeUpdate() List<Produto> resultado = query.getResultList(); Produto produto = query.getSingleResult();
  • 109. JAVAEE7 Sintaxe de uma operação SELECT •A principal operação de JPQL é SELECT, que tem a seguinte sintaxe geral cláusula_select cláusula_from
 [cláusula_where] [cláusula_group_by] [cláusula_having] [cláusula_order_by] SELECT p.nome FROM Produto AS p WHERE p.codigo = '123' Define o contexto da pesquisa e declara p como alias da entidade Produto Seleciona valores no contexto da entidade p Parâmetro Restrição da seleção SELECT p 
 FROM Produto p 
 WHERE p.nome = :n Alias (AS é opcional) Parâmetro de query Seleção de entidades (cláusulas opcionais)
  • 110. JAVAEE7 Cláusula FROM •A cláusula FROM define o escopo informando qual ou quais os objetos que estão sendo pesquisados, e declara aliases usados no resto do query. •Cada alias tem um identificador e um tipo. •O identificador é qualquer palavra não-reservada e o tipo é o nome da entidade identificada como @Entity. •A palavra-chave AS (opcional) conecta o tipo ao identificador •A cláusula FROM também pode selecionar múltiplos objetos e atributo e incluir vários conectores de JOIN (inner join, left outer join). ... FROM Produto AS p Tipo (Entidade) Identificador (alias)
  • 111. JAVAEE7 Cláusula SELECT •Informa o que se deseja obter. Pode retornar •entidades, •atributos dos objetos, •resultados de expressões, •tuplas envolvendo atributos, entidades e resultados de expressões •Pode ser seguida de DISTINCT para eliminar valores duplicados •SELECT utiliza o alias declarado na cláusula FROM: SELECT p FROM Produto p SELECT DISTINCT p FROM Produto p SELECT p.codigo FROM Produto p SELECT DISTINCT p.codigo FROM Produto p
  • 112. JAVAEE7 Cláusula WHERE •É opcional e restringe os resultados da pesquisa com base em uma ou mais expressões condicionais concatenadas.As expressões podem usar: •literais (strings, booleanos ou números), •identificadores (declarados no FROM), •operadores, •funções •parâmetros identificados por número (?1, ?2) ou identificador (:nome, :item). •Os literais usados nas pesquisas podem ser: •Strings, representados entre apóstrofes: 'nome' •Números, que têm mesmas regras de literais Java long e double •Booleanos, representados por TRUE e FALSE (case-insensitive)
  • 113. JAVAEE7 Operadores de WHERE •Navegação . •Expressões matemáticas +, -, *, / •Expressões de comparação =, >, >=, <, <=, <> •Operadores lógicos NOT,AND, OR •Outros operadores: [NOT] BETWEEN, [NOT] IN, [NOT] LIKE, IS [NOT] NULL, IS [NOT] EMPTY, [NOT] MEMBER •O operador LIKE possui operadores adicionais: •_ representa um único caractere •% representa uma seqüência de zero ou mais caracteres • caractere de escape (necessário para usar _ ou %) literalmente
  • 114. JAVAEE7 Funções •Funções podem aparecer em cláusulas WHERE ou SELECT: •Manipulação de strings (WHERE): CONCAT, SUBSTRING,TRIM, LOWER, UPPER, LEADING,TRAILING, BOTH, LENGTH, LOCATE •Funções aritméticas (WHERE): ABS, SQRT, MOD, SIZE •Data e hora (WHERE): CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP •Funções de agregação (SELECT): COUNT, MAX, MIN,AVG, SUM
  • 115. JAVAEE7 Exemplos •Encontre todos os produtos que são chips e cuja margem de lucro é positiva SELECT p 
 FROM Produto p 
 WHERE (p.descricao = 'chip' AND (p.preco - p.custo > 0) •Encontre todos os produtos cujo preço é pelo menos 1000 e no máximo 2000 SELECT p
 FROM Produto p 
 WHERE p.preco BETWEEN 1000 AND 2000
  • 116. JAVAEE7 Exemplos •Encontre todos os produtos cujo fabricante é Sun ou Intel SELECT p
 FROM Produto p 
 WHERE p.fabricante IN ('Intel', 'Sun') •Encontre todos os produtos com IDs que começam com 12 e terminam em 3 SELECT p
 FROM Produto p 
 WHERE p.id LIKE '12%3'
  • 117. JAVAEE7 Exemplos •Encontre todos os produtos que têm descrições null SELECT p
 FROM Produto p 
 WHERE p.descricao IS NULL •Encontre todos os pedidos que não têm itens (coleção) SELECT pedido 
 FROM Pedido pedido 
 WHERE pedido.itens IS EMPTY
  • 118. JAVAEE7 Exemplos •Retorne os pedidos que contem um determinado item (passado como parâmetro) SELECT pedido
 FROM Pedido pedido 
 WHERE :item IS MEMBER pedido.itens •Encontre produtos com preços entre 1000 e 2000 ou que tenham código 1001 SELECT p
 FROM Produto p 
 WHERE p.preco BETWEEN 1000 AND 2000 OR codigo = 1001
  • 119. JAVAEE7 Exemplos com relacionamentos •Selecione todos os clientes com pedidos que tenham total maior que 1000: SELECT c 
 FROM Cliente c, IN(c.pedidos) p 
 WHERE p.total > 1000 •O mesmo query poderia ser escrito desta forma, expondo o join: SELECT c 
 FROM Cliente c 
 INNER JOIN c.pedidos AS p 
 WHERE p.total > 1000
  • 120. JAVAEE7 Exemplos com relacionamentos •Lances onde o item de categoria iniciando em “Celular” tenha obtido lance >1000: SELECT lance
 FROM Lance lance 
 WHERE lance.item.categoria.nome LIKE 'Celular%' 
 AND lance.item.lanceObtido.total > 1000 •Queries equivalentes. O primeiro expõe um dos joins e o segundo expõe todos: SELECT lance
 FROM Lance lance
 JOIN lance.item item 
 WHERE item.categoria.nome LIKE 'Celular%'
 AND item.lanceObtido.total > 1000 SELECT lance
 FROM Lance AS lance
 JOIN lance.item AS item 
 JOIN item.categoria AS cat 
 JOIN item.lanceObtido AS lanceVencedor 
 WHERE cat.nome LIKE 'Celular%'
 AND lanceVencedor.total > 1000
  • 121. JAVAEE7 Exemplos usando funções •Encontre a média do total de todos os pedidos: SELECT AVG(pedido.total)
 FROM Pedido pedido •Obtenha a soma dos preços de todos os produtos dos pedidos feitos no bairro de Botafogo: SELECT SUM(item.produto.preco) 
 FROM Pedido pedido 
 JOIN pedido.itens item 
 JOIN pedido.cliente cliente 
 WHERE cliente.bairro = 'Botafogo' 
 AND cliente.cidade = 'Rio de Janeiro'
  • 122. JAVAEE7 Exemplos usando funções •Obtenha a contagem de clientes agrupadas por bairro: SELECT cliente.bairro, COUNT(cliente) 
 FROM Cliente cliente
 GROUP BY cliente.bairro •Obtenha o valor médio dos pedidos, agrupados por pontos, para os clientes que têm entre 1000 e 2000 pontos: SELECT c.pontos, AVG(pedido.total) 
 FROM Pedido pedido 
 JOIN pedido.cliente c 
 GROUP BY c.pontos 
 HAVING c.pontos BETWEEN 1000 AND 2000
  • 123. JAVAEE7 Exemplos com subqueries •É possível usar os resultados de um query como parâmetro de outro através de subqueries. O query abaixo usa como restrição o resultado de um query que será testado com EXISTS. •"Obtenha os empregados que são casados com outros empregados" SELECT DISTINCT emp 
 FROM Empregado emp 
 WHERE EXISTS (SELECT conjuge 
 FROM Empregado conjuge
 WHERE conjuge = emp. conjuge)
  • 124. JAVAEE7 Exemplos com subqueries: All/Any •ALL e ANY são usados com subqueries •ALL retorna true se todos os valores retornados forem true •ANY só retorna true se resultado for vazio ou se todos os valores forem false •"Retorne apenas os produtos cujo preço seja maior que o valor incluído em todos os orçamentos" SELECT produto 
 FROM Produto p 
 WHERE p.preco > ALL(SELECT o.item.preco 
 FROM Orcamento o 
 WHERE o.item.codigo = p.codigo)
  • 125. JAVAEE7 Queries que retornam tuplas •Queries que retornam múltiplos valores têm resultados armazenados em arrays de objetos • Cada índice do array corresponde respectivamente ao item selecionado, na ordem em que é expresso em JPQL •Exemplo: a query abaixo retorna três valores: um Long, um String e um Diretor, que é uma entidade, respectivamente. @Entity class Filme { @Id private Long id; private String imdb; private String titulo; @ManyToMany private Diretor diretor; ... } SELECT f.id, f.titulo, d 
 FROM Filme f join f.diretores d 
 WHERE d.nome LIKE ‘%Allen’ @Entity class Diretor { @Id private Long id; private String nome; ... }
  • 126. JAVAEE7 Queries que retornam tuplas •A execução so query irá retornar cada elemento como um array do tipo Object[] onde cada valor será armazenado em um índice •Se houver mais de um resultado, o tipo retornado será List<Object[]> •Para obter os dados da query anterior pode-se usar: List<Object[]> resultado = (List<Object[]>)query.getResultAsList(); for(Object obj : resultado) { Long id = (Long)obj[0]; String titulo = (String)obj[1]; Diretor diretor = (Diretor)obj[2]; ... }
  • 127. JAVAEE7 Tuplas como DataTransferObject (DTO) •Queries que retornam tuplas podem ter o objetivo de gerar relatórios, ou para coletar dados para uma interface •Os dados podem ser guardados em um objeto especialmente criado para recebê-los: package com.acme.filmes; public class DataTransferObject { private Long id; private String titulo; private Diretor diretor; public DataTransferObject(Long id, String titulo, Diretor diretor) { this.id = id; this.titulo = titulo; this.diretor = diretor; } ... }
  • 128. JAVAEE7 Tuplas como DataTransferObject (DTO) •O objeto pode então ser instanciado dentro do loop: List<Object[]> resultado = (List<Object[]>)query.getResultAsList(); for(Object obj : resultado) { Long id = (Long)obj[0]; String titulo = (String)obj[1]; Diretor diretor = (Diretor)obj[2]; DataTransferObject dto = new DataTransferObject(id, titulo, director); // envia dto para algum lugar }
  • 129. JAVAEE7 Tuplas como DataTransferObject (DTO) •Há uma sintaxe de SELECT que elimina a necessidade de escrever todo esse código, chamando o construtor diretamente dentro do query: •JPA 2.1 requer que o construtor use o nome qualificado da classe •O query retorna uma List<DataTransferObject> em vez de List<Object[]>, que pode ser retornada diretamente para o cliente: SELECT new com.acme.filmes.DataTransferObject(f.id, f.titulo, d) 
 FROM Filme f join f.diretores d 
 WHERE d.nome LIKE ‘%Allen’ @Named public class ManagedBean { public List<DataTransferObject> getDataToPopulateComponent() { ... return query.getResultAsList(); } ... }
  • 130. JAVAEE7 Tuplas em JPA Criteria •CriteriaQuery oferece outra alternativa de solução para este problema com a interface javax.persistence.Tuple •Os resultados ainda precisam ser extraídos individualmente, mas são retornados em um objeto Tuple (em vez de Object[]) •O conteúdo de Tuple pode ser recuperado como uma List: tupla.get(0), tupla.get(1), etc.
  • 131. JAVAEE7 Named Queries •Queries podem ser declarados em anotações e recuperadas pelo nome •Isto, em geral é uma boa prática porque mantém todos os queries juntos, e pode facilitar a manutenção deles •Por outro lado, os mantém distante do código que cria os queries e preenche os parâmetros, que pode dificultar o uso. •Para declarar queries desta forma, use a anotação @NamedQueries: @Entity @NamedQueries({ @NamedQuery(name="produtoMaisBarato", query="SELECT x FROM Produto x WHERE x.preco > ?1"), @NamedQuery(name="produtoPorNome", query="SELECT x FROM Produto x WHERE x.nome = :nomeParam") }) public class Produto { ... }
  • 132. JAVAEE7 Uso de Named Queries •Para usar, chame o query pelo nome quando usar o EntityManager através do método createNamedQuery(), e preencha seus parâmetros se houver: EntityManager em = ... Query q1 = em.createNamedQuery("produtoMaisBarato"); q1.setParameter(1, 10.0); List<Produto> resultado1 = q1.getResultList(); Query q2 = em.createNamedQuery("produtoPorNome"); q2.setParameter("nomeParam", 10.0); List<Produto> resultado2 = q2.getResultList();
  • 133. JAVAEE7 Exercícios •13. Escreva os seguintes queries em JPQL usando a Hierarquia 5: •Todos os livros com idioma = PT ou EN •Livros cujo título tenha a palavra "the" e id entre 2 e 10 •Livros que tenham um autor chamado "John" •Autores que tenham mais de um livro •Editoras que tenham mais de um título em idioma = EN •14. Escreva os seguintes queries usando a Hierarquia 2: •Todos os filmes com duração maior que 100 minutos •Filmes produzidos entre 1950 e 1990 •Diretores com mais de 3 filmes
  • 134. JAVAEE7 Exercícios •15. Escreva os seguintes queries em JPQL usando a Hierarquia 4: •Nomes de todos os Participantes da etapa com origem: "Nova York" e destino: "Moscow" que possuem ingresso com status = "Pago" •16. Escreva os seguintes queries usando a Hierarquia 3: •Valor total (para cada item: item.quantidade * produto.preco) de cada pedido de status="finalizado" do cliente de userid=Fred •Soma (sum) e média (avg) dos valores totais de todos os pedidos
  • 136. JAVAEE7 Criteria •Criteria é uma API do JPA que permite a construção de queries dinâmicos e verificados em tempo de compilação, usando objetos •Este query JPQL select p from Produto p where p.preco < 50.0 •Pode ser expresso em Criteria da seguinte forma: CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Produto> query =
 cb.createQuery(Produto.class); // tipo do select Root<Produto> raiz = query.from(Produto.class); // tipo do from Predicate condicao = cb.lessThan(raiz.get("preco"), 50.0); // predicado query.where(condicao); // adiciona a clausula where query.select(raiz); // diz o que vai ser selecionado
  • 137. JAVAEE7 Construção de um query •Queries de Criteria são um grafo de objetos •A raiz do grafo é encapsulado no CriteriaQuery •Um query mínimo requer o uso de três classes do pacote javax.persistence.criteria: •CriteriaBuilder, que encapsula vários métodos para construir o query, •CriteriaQuery, que representa a consulta •Root que é raiz da consulta e representa os objetos selecionados pela cláusula FROM
  • 138. JAVAEE7 Construção de um query •1) Criar um CriteriaQuery através da classe CriteriaBuilder: CriteriaBuilder builder =
 entityManagerFactory.getCriteriaBuilder(); •2) obter o objeto que irá encapsular o query: CriteriaQuery<Produto> query = 
 builder.createQuery( Produto.class ); •3) O objeto raiz do grafo é declarado através da interface Root, que constrói a cláusula “from” do query. Isto é equivalente a fazer “from Produto p” em JPQL: Root<Produto> p = query.from(Produto.class); •4) Finalmente constrói-se a cláusula “select” do query usando o método select(): query.select(p); •O query está pronto. Neste momento ele é equivalente ao string JPQL.
  • 139. JAVAEE7 Execução de um Query •Uma vez pronto, pode-se executar um Criteria Query da mesma forma que um JPQL Query •1) Passe o objeto query como parâmetro de um TypedQuery: TypedQuery<Produto> query = 
 em.createQuery(query); •2) Chame um método de execução pára obter os resultados List<Produto> resultado =
 query.getResultList();
  • 140. JAVAEE7 Consultas que retornam tuplas •Consultas que retornam múltiplos objetos podem ser feitas com from(), join() ou fetch() e métodos similares •O query JPQL: SELECT p1, p2 FROM Produto p1, Produto p2 •Pode ser escrito usando Criteria da seguinte forma: CriteriaQuery<Tuple> criteria = cb.createQuery(Tuple.class); Root<Produto> p1 = criteria.from(Produto.class); Root<Produto> p2 = criteria.from(Produto.class); criteria.multiselect(p1, p2);
  • 141. JAVAEE7 Outer Join (Left Join) •Um join como na query abaixo: SELECT item, produto.nome 
 FROM Item item 
 LEFT OUTER JOIN item.produto produto •Pode ser escrito em Criteria da seguinte forma: CriteriaQuery<Tuple> criteria = cb.createQuery(Tuple.class); Root<Item> item = criteria.from(Item.class); Join<Item> produto = item.join("produto", JoinType.LEFT); criteria.multiselect(item, produto.get("nome"));
  • 142. JAVAEE7 Fetch Join •A interface Join retornada pelo método join() é subinterface da interface From, portanto pode ser usada em metódos que esperam um From •Um join usando fetch como este em JPQL: SELECT item 
 FROM Item item 
 JOIN FETCH item.produto •Pode ser expresso em Criteria usando a seguinte sintaxe: CriteriaQuery<Item> criteria = cb.createQuery(Item.class); Root<Item> item = criteria.from(Item.class); Fetch<Item, Produto> produto = item.fetch("produto"); criteria.select(item);
  • 143. JAVAEE7 Interfaces Criteria Expression<X> TupleElement<X> Selection<X> Path<X> From<Z,X> Root<Z,X> Join<Z,X> PluralJoin<Z, C, E> CollectionJoin<Z, E> SetJoin<Z, E> ListJoin<Z, E> MapJoin<Z, K,V> Predicate<X> SubQuery<X> ParameterExpression<X>
  • 144. JAVAEE7 Principais interfaces •Expression – São construídas compondo outras expressões. Retornada em métodos de CriteriaQuery e CriteriaBuilder (sum(), diff(), equal()) •Predicate – Conjunção (ou disjunção) das restrições de query representado por valor booleano.A cláusula where recebe um Predicate. São construídos compondo outros predicados. Retornado em métodos de CriteriaBuilder (equal(), and(), or(), between()) •Path – Representa caminho de navegação em um grafo. Ex: objeto.referencia.atributo. O método get() de Root acessa atributos de objetos através de expressões de path. •Join – Representa join para uma @Entity, objeto @Embeddable ou @Basic •Selection – Qualquer item retornado em um resultado de query, como uma expressão (Expression), subquery (SubQuery), predicado (Predicate), caminho (Path), etc. •SubQuery – Representa um subquery
  • 145. JAVAEE7 Métodos de CriteriaQuery e Subquery •A hierarquia que representa um query em Criteria possui duas classes •CriteriaQuery (query principal) •Subquery •Elas têm a superclasse AbstractQuery em comum e métodos que representam cláusulas e outras partes de um query: •Herdados de AbstractQuery (valem para queries principais e subqueries): 
 distinct(), from(), groupBy(), having(), subQuery(), where() •Definidos em CriteriaQuery (valem apenas para queries principais): 
 multiselect(), select() •Definidos em Subquery (valem apenas para subqueries): 
 correlate(), getParent()
  • 146. JAVAEE7 CriteriaBuilder •A classe CriteriaBuilder possui métodos para a construção de todas as expressões usadas nas cláusulas dos queries e subqueries •Encapsuladas em instâncias de Expression ou subclasses •Podem ser criadas chamando os factory methods de CriteriaBuilder •Envolvem desde a criação de literais até condicionais, expressões boleanas, de comparação, etc. Expression<Integer> i1 = builder.literal(123); Expression<Integer> i2 = builder.sum(3,4); Predicate p1 = builder.and(true, false); Predicate p2 = builder.not(p1);
  • 147. JAVAEE7 Exemplos •Encontre todos os produtos que são chips e cuja margem de lucro é positiva CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Produto> query = cb.createQuery(Produto.class); Root<Produto> root = query.from(Produto.class); Predicate igual = cb.equal(root.get("descricao"), "chip"); Expression<Double> subtracao = cb.diff(root.get("preco"), root.get("custo")); Predicate maiorQue = cb.greaterThan(subtracao, 0.0); Predicate clausulaWhere = cb.and(igual, maiorQue); query.where(clausulaWhere); query.select(root); TypedQuery<Produto> q = em.createQuery(query);
  • 148. JAVAEE7 Exemplos •Encontre todos os produtos cujo preço é pelo menos 1000 e no máximo 2000 CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Produto> query = cb.createQuery(Produto.class); Root<Produto> root = query.from(Produto.class); Predicate between = cb.between(root.get("preco"), 1000.0, 2000.0); query.where(between); query.select(root);
  • 149. JAVAEE7 Exemplos •Encontre todos os produtos cujo fabricante é Sun ou Intel CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Produto> query = 
 cb.createQuery(Produto.class); Root<Produto> root = query.from(Produto.class); query.where(root.get("fabricante").in("Intel", "Sun")); query.select(root);
  • 150. JAVAEE7 Exemplos •Encontre todos os produtos com IDs que começam com 12 e terminam em 3 CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Produto> query = 
 cb.createQuery(Produto.class); Root<Produto> root = query.from(Produto.class); query.where(cb.like(root.get("id"), "12%3")); query.select(root);
  • 151. JAVAEE7 Exemplos •Encontre todos os produtos que têm descrições null CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Produto> query =
 cb.createQuery(Produto.class); Root<Produto> root = query.from(Produto.class); query.where(cb.isNull(root.get("descricao"))); query.select(root);
  • 152. JAVAEE7 Exemplos •Encontre todos os pedidos que não têm itens (coleção) CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Pedido> query = 
 cb.createQuery(Pedido.class); Root<Pedido> root = query.from(Pedido.class); query.where(cb.isEmpty(root.get("itens"))); query.select(root);
  • 153. JAVAEE7 Exemplos •Retorne os pedidos que contem um determinado item (passado como parâmetro) Item item = new Item(); // item a ser testado // ... CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Pedido> query =
 cb.createQuery(Pedido.class); Root<Pedido> root = query.from(Pedido.class); Predicate isMember =
 cb.isMember(item, root.get("itens")); query.where(isMember); query.select(root);
  • 154. JAVAEE7 Exemplos •Encontre produtos com preços entre 1000 e 2000 ou que tenham código 1001 CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Produto> query = 
 cb.createQuery(Produto.class); Root<Produto> root = query.from(Produto.class); Predicate between = 
 cb.between(root.get("preco"), 1000.0, 2000.0); Predicate igual = 
 cb.equal(root.get("codigo"), 1001); query.where(cb.or(between, igual)); query.select(root);
  • 155. JAVAEE7 Exemplos com relacionamentos •Selecione todos os clientes com pedidos com total maior que 1000: CriteriaBuilder cb = em.getCriteriaBuilder();
 CriteriaQuery<Cliente> query = cb.createQuery(Cliente.class);
 Root<Cliente> root = query.from(Cliente.class);
 Path<Pedido> pedido = root.get("pedidos");
 query.where(cb.greaterThan(pedido.get("total"), 1000.0));
 query.select(root); •Mesmo query usando um inner join explícito: CriteriaBuilder cb = em.getCriteriaBuilder();
 CriteriaQuery<Cliente> query = cb.createQuery(Cliente.class);
 Root<Cliente> root = query.from(Cliente.class);
 Join<Cliente, Pedido> pedido = root.join("pedidos");
 query.where(cb.greaterThan(pedido.get("total"), 1000.0));
 query.select(root);
  • 156. JAVAEE7 Exemplos com relacionamentos •Lances onde o item é de categoria que começa com “Celular” e teve lance > 1000: CriteriaBuilder cb = em.getCriteriaBuilder();
 CriteriaQuery<Lance> query = cb.createQuery(Lance.class); 
 Root<Lance> root = query.from(Lance.class); 
 query.where(cb.and(
 cb.like(root.get("item").get("categoria").get("nome"), "Celular%"),
 cb.greaterThan(root.get("item").get("lanceObtido").get("total")1000.0)));
 query.select(root); •Mesmo query usando vários inner joins explícitos: CriteriaBuilder cb = em.getCriteriaBuilder();
 CriteriaQuery<Lance> query = cb.createQuery(Lance.class); 
 Root<Lance> root = query.from(Lance.class); 
 Join<Lance, Item> item = root.join("item");
 Join<Item, Categoria> cat = item.join("categoria");
 Join<Item, Lance> vencedor = item.join("lanceObtido");
 query.where(cb.and(cb.like(cat.get("nome"), "Celular%"),
 cb.greaterThan(vencedor.get("total"), 1000.0)));
 query.select(root);
  • 157. JAVAEE7 Exemplos •Encontre a média do total de todos os pedidos: CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Double> query = 
 cb.createQuery(Double.class); // avg retorna Double Root<Pedido> root =
 query.from(Pedido.class); // from Ingresso i Expression<Double> media = cb.avg(root.get("total")); query.select(media);
  • 158. JAVAEE7 Exemplos •Obtenha a soma dos preços de todos os produtos dos pedidos feitos no bairro de Botafogo: CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<BigDecimal> query = cb.createQuery(BigDecimal.class); Root<Pedido> root = query.from(Pedido.class); Join<Pedido, Item> item = root.join("itens"); Join<Pedido, Cliente> cliente = item.join("cliente"); Predicate where = cb.and( cb.equal(cliente.get("bairro"), "Botafogo"), cb.equal(cliente.get("cidade"), "Rio de Janeiro") ); query.where(where); Expression<BigDecimal> total = 
 cb.sum(item.get("produto").get("preco")); query.select(total);
  • 159. JAVAEE7 Exemplos •Obtenha a contagem de clientes agrupadas por bairro: CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Object[]> query = 
 cb.createQuery(Object[].class); Root<Cliente> root = query.from(Cliente.class); query.multiselect(root.get("bairro"), cb.count(root)); query.groupBy(root.get("bairro")); TypedQuery<Object[]> q = em.createQuery(query); ...
  • 160. JAVAEE7 Exemplos •Obtenha o valor médio dos pedidos, agrupados por pontos, para os clientes que têm entre 1000 e 2000 pontos: CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Object[]> query = 
 cb.createQuery(Object[].class); Root<Pedido> root = query.from(Pedido.class); query.multiselect(root.get("pontos"), 
 cb.avg(root.get("total"))); Join<Pedido, Cliente> cliente = root.join("cliente"); query.groupBy(cliente.get("pontos")); query.having(cb.between(cliente.get("pontos"), 
 1000.0, 2000.0));
  • 161. JAVAEE7 Exemplos com subqueries •Obtenha os empregados que são casados com outros empregados: CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Empregado> query = 
 cb.createQuery(Empregado.class); Root<Empregado> root = query.from(Empregado.class); Subquery<Empregado> subquery = 
 query.subquery(Empregado.class); Root<Empregado> conjuge = 
 subquery.from(Empregado.class); subquery.where(cb.equal(conjuge.get("conjuge "), 
 root.get("conjuge "))); subquery.select(conjuge); query.where(cb.exists(subquery)); query.select(root).distinct(true);
  • 162. JAVAEE7 Exemplos com subqueries (All/Any) •Retorne apenas os produtos cujo preço seja maior que o valor incluído em todos os orçamentos: CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Produto> query = cb.createQuery(Produto.class); Root<Produto> root = query.from(Produto.class); Subquery<Empregado> subquery = 
 query.subquery(Empregado.class); Root<Orcamento> orcamento = 
 subquery.from(Orcamento.class); subquery.where(cb.equal(orcamento.get("item ").get("codigo"), 
 root.get("codigo"))); subquery.select(orcamento.get("item").get("preco")); query.where(cb.greaterThan(root.get("preco"), 
 cb.all(subquery))); query.select(root);
  • 163. JAVAEE7 Select com DataStransferObject •O query usando select com construtor mostrado na seção anterior com JPQL pode ser construído com Criteria da forma abaixo: CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Lugares> query = 
 cb.createQuery(DataTransferObject.class); Root<Filme> root = query.from(Filme.class); Join<Filme, Diretor> diretor = root.join("etapas"); query.where(cb.like(root.get("nome"), "%Allen")); query.select(cb.construct(Lugares.class,
 etapa.get("origem").get("nome"), 
 etapa.get("destino").get("nome"))
 );
  • 164. JAVAEE7 Typesafe query •É bem mais fácil encontrar erros em queries Criteria, comparados a JPQL, porque o compilador ajuda na tarefa e detecta queries incorretos. •Mas erros de digitação ainda podem acontecer já que a leitura dos campos das entidades feita através de um get() recebe um String. •Por exemplo, a linha abaixo para ler o campo “preco” não contém erros de compilação: Predicate condicao = qb.lt(raiz.get("prco"), 50.0); •Mas se o string estiver errado, o query está incorreto: existem erros de sintaxe em queries Criteria que também não são capturados em tempo de compilação!
  • 165. JAVAEE7 Typesafe query •A solução é o o typesafe query: •O nome do atributo foi informado através de código Java, usando um atributo estático e público da classe Produto_. •Produto_.class é um metamodelo estático (static metamodel). •Usando atributos através do metamodelo torna os queries typesafe CriteriaBuilder qb = em.getCriteriaBuilder(); CriteriaQuery<Produto> cq = qb.createQuery(Produto.class); Root<Produto> raiz = cq.from(Produto.class) Predicate condicao = qb.lt(raiz.get(Produto_.preco), 50.0); cq.where(condicao); TypedQuery<Person> query = em.createQuery(cq);
  • 166. JAVAEE7 Geração de metamodels •Metamodelos precisam ser geradas. IDEs que suportam JPA 2 têm ferramentas para gerá-los. Projetos Maven com EclipseLink podem fazer a geração em uma das fases do POM.xml com um plug-in: •O plugin precisa ser configurado e usará as classes declaradas no persistence.xml para gerar metamodelos durante a fase de geração de código do build (veja a documentação para mais detalhes) <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId> <version>2.5.0</version> </dependency>
  • 167. JAVAEE7 Exercícios •17. Implemente um dos queries do exercício 13 usando Criteria •18. Implemente um dos queries do exercício 14 usando Criteria •19. Implemente um dos queries do exercício 15 usando Criteria •20. Implemente um dos queries do exercício 16 usando Criteria •21. Implemente um bean que realize uma pesquisa dinâmica em Livros, filtrando por autor, isbn e título. Crie um mecanismo que permita construir um query dinâmico: •Se nenhum campo estiver preenchido, a busca será feita sem filtros •Se algum campo estiver preenchido, ele deve ser acrescentado na cláusula where da pesquisa
  • 169. JAVAEE7 Transações em JPA •Podem ser •Distribuídas com 2-phase commit (JTA) •Configuradas como um recurso local (RESOURCE_LOCAL) •Apenas transações JTA são gerenciadas pelo container (CMT - Container- Managed Transactions) para configurar suporte transacional de forma transparente e declarativa •Transações JTA também podem ser controladas programaticamente (BMT - Bean-Managed Transactions) através da API da classe UserTransaction, que pode ser injetada como resource em componentes Java EE
  • 170. JAVAEE7 Resource Local •Usada em ambientes Java SE ou onde não há suporte a transações distribuídas •getTransaction() obtém contexto transacional para operações de persistência •Transações são delimitadas pela chamada dos métodos begin() e commit()/rollback(): public class AlunoDAO { private EntityManagerFactory emf; AlunoDAO() { emf = Persistence.createEntityManagerFactory("escola-PU");} public void addAluno(Aluno aluno) { EntityManager em = emf.getEntityManager(); try em.getTransaction().begin(); em.persist(aluno); em.getTransaction().commit(); } catch(Exception e) { em.rollback(); } finally { em.close(); } } } <persistence-unit name="escola-PU"
 transaction-type="RESOURCE_LOCAL"> Em persistence.xml:
  • 171. JAVAEE7 JTA (Java Transaction API) •Disponível em servidores Java EE e suporta transações distribuídas (2-phase) •Pode ser obtida e injetada como um @Resource em WebServlets, EJBs, e outros componentes que rodam no container Java EE •Em ambientes CDI também pode ser injetada com @Inject public class AlunoDAOBean { @PersistenceContext(unitName="escola-PU") private EntityManager; @Resource UserTransaction ut; public void addAluno(Aluno aluno) { try ut.begin(); em.persist(aluno); ut.commit(); } catch(Exception e) { ut.rollback(); } finally { em.close(); } } } <persistence-unit name="escola-PU"
 transaction-type="JTA"> Em persistence.xml:
  • 172. JAVAEE7 CMT (JTA) em EJB •Em EJB transações gerenciadas pelo container (CMT),JTA é o comportamento default e é transparente •Todos os métodos de um SessionBean são automaticamente incluídos em um contexto transacional @Stateless public class AlunoSessionBean { @PersistenceContext 
 EntityManager em; public void addAluno(Aluno aluno) { em.persist(aluno); } } <persistence-unit name="escola-PU"
 transaction-type="JTA"> Em persistence.xml:
  • 173. JAVAEE7 CMT (JTA) em CDI •Em CDI o mesmo comportamento pode ser obtido nos métodos declarados como @Transactional @Model public class AlunoSessionBean { @Inject
 EntityManager em; @Transactional public void addAluno(Aluno aluno) { em.persist(aluno); } } <persistence-unit name="escola-PU"
 transaction-type="JTA"> Em persistence.xml:
  • 174. JAVAEE7 Cache •O JPA possui dois níveis de cache •O Contexto de Persistência, controlado pelo EntityManager (L1) •Cache L2: Mecanismo compartilhado. •Cache é um recurso de performance que deve ser usado com cuidado •Há risco de resultar em inconsistência de dados •Pode inclusive introduzir bugs •O custo-benefício com os ganhos de performance poderá compensar o esforço extra de gerenciar o cache
  • 175. JAVAEE7 Cache L1 (contexto de persistência) e L2