Slides Jpa - Novo
-
Upload
rafael-carlos-da-silva -
Category
Documents
-
view
437 -
download
0
Transcript of Slides Jpa - Novo
1
Curso de Linguagem Java
Marcos Mendes
2010
2
JPA - Java Persistence API(Beans de Entidade)
Referência Bibliográfica: Enterprise JavaBeans 3.0 Bill Burke & Richard Monson Editora. Prentice Hall Desenvolvendo Aplicações Web com JSP, Servlets, JSF, Hibernate, EJB 3 e Ajax
Edson GonçalvesEditora Ciência Moderna
Revista JavaMagazine edições 39 e 44 Revista MundoJava edição 24 Página da Sun sobre a tecnologia JPA http://java.sun.com/javaee/technologies/persistence.jsp
3
JPA – Java Persistence API Arquitetura
Aplicação Java
Java Persistence API
Provedor JPA
API JDBC
Driver JDBC
BancoDe Dados
4
JPA – Java Persistence API Conceitos
Parte integrante da JavaEE 5 Disponível a partir da Java5 Definida na JSR220 – Enterprise JavaBeans 3.0 Padroniza o Mapeamento Objeto Relacional Não depende de Container para funcionar Baseada no conceito de POJOs (Plain Old Java
Object) Utiliza amplamente Annotations (Progamação
Declarativa) Pacote javax.persistence
5
JPA – Java Persistence API Entidades
Os objetos persistentes são denominados Entities(Entidades)As Classes de Entidades devem atender a alguns requisitos:
Ser anotadas com a anotação javax.persistence.Entity Possuir um identificador(chave primária) a não ser que
seja uma subclasse. Possuir um construtor public ou protected sem parâmetros
(podem ter outros construtores). Não podem ser declaradas como final. Métodos ou
variáveis de instância não podem ser declarados como final.
Se forem passados como parâmetro em uma chamada de método remota, a classe precisa implementar a interface java.io.Serializable.
6
JPA – Java Persistence API Variáveis de instância devem ser declaradas
como private, protected ou "default", e somente podem ser acessadas diretamente por métodos da classe de entidade. Os clientes podem acessar o estado da entidade através de métodos acessores ou métodos de negócio.
Campos Persistentes e Propriedades em uma Classe de EntidadeO estado persistente de uma entidade pode ser acessado através das variáveis de instância ou através de métodos acessores no estilo JavaBeans (getters e setters). O estado é representado através dos seguintes tipos na linguagem Java:
Tipos Java primitivos Java.lang.String
7
JPA – Java Persistence API Outros tipos serializáveis como: Wrappers de
tipos primitivos, java.math.BigInteger, java.math.BigDecimal, java.util.Date, java.util.Calendar, java.sql.Date, java.sql.Time, java.sql.TimeStamp, tipos serializáveis definidos pelo usuário, byte[], Byte[], char[], Character[], tipos enumerados, outras entidades e/ou coleções de entidades, classes "embeddable".
Outras entidades e/ou Coleções de entidades. Classes embutidas (Embeddable)
O mapeamento do estado das entidades é feito com anotações, ou nos campos persistentes, ou então nos métodos getters, nunca em ambos, em uma única entidade.
8
JPA – Java Persistence API Unidade de Persistência (Persistence Unit)
Conjunto de classes mapeadas para um banco de dados
relacional que são gerenciadas por um Entity Manager.
Esse mapeamento é feito através de um arquivo
descritor de implantação chamado persistence.xmlpersistence.xml
que é gravado na pasta META-INFMETA-INF e que pode conter a
configuração de várias unidades de persistência.
Contexto de Persistência(Persistence Context)
Ambiente (sessão) que envolve o conjunto de instâncias
de entidades gerenciadas pelo Entity Manager.
9
JPA – Java Persistence API Gerenciador de Entidades (Entity Manager)
javax.persistence.EntityManager
Serviço que gerenciará o conjunto de entidades registradas dentro de um contexto. Monitorando as alterações feitas nos objetos deste contexto de persistência, gravando assim essas alterações no banco de dados.
Provedor de Persistência (Persistence Provider)
É como se fosse um driver JPA para uma determinada ferramenta de mapeamento objeto-relacional. Mais especificamente, é a classe que implementa a interface javax.persistence.PersistenceProvider
São alguns exemplos de fornecedores de provedores de persistência:
Oracle TopLink, Hibernate, Kodo, Open JPA, etc.
10
JPA – Java Persistence API Ciclo de Vida / Estados de um objeto
Objeto não existe
DETACHED
NEW
MANAGED
REMOVED
new
remove( )
persist( )merge( )
find( )
clear( ) ou quando o
EntityManager é fechado
Garbage Collector
11
JPA – Java Persistence API Mapeamento Básico de Entidades
É feito com o uso de anotações nas classes persistentes. @Entity@Entity – Marca uma classe como entidade persistente. Esta
classe deve possuir um construtor sem parâmetros. @Table@Table – Define o nome da Tabela onde os objetos serão
persistidos. @Id@Id – Define o atributo que constitui a chave primária. @GeneratedValue@GeneratedValue – Define um campo auto-incremento. @Column@Column – Define o nome da coluna onde o atributo será salvo. @Temporal@Temporal – Fornece informações adicionais ao provedor de
persistência sobre o mapeamento de um atributo do tipo java.util.Date ou java.util.Calendar. Utiliza os valores TemporalType.DATE, TemporalType.TIME ou TemporalType.TIMESTAMP.
@Transient@Transient – Define que um atributo não será salvo no banco de dados.
12
JPA – Java Persistence API Exemplo de Entidade
import javax.persistence.*;
import java.util.*;
@Entity@Entity
@Table (name = "Pessoa")@Table (name = "Pessoa")
public class Pessoa {
@Id@Id
@GeneratedValue (strategy=GenerationType.IDENTITY)@GeneratedValue (strategy=GenerationType.IDENTITY)
@Column (name = "id", nullable = false)@Column (name = "id", nullable = false)
private int id;
@Column (name = "nome", length = 50, nullable = false)@Column (name = "nome", length = 50, nullable = false)
private String nome;
@Column (name = "dataNasc")@Column (name = "dataNasc")
@Temporal (TemporalType.DATE)@Temporal (TemporalType.DATE)
private Date dataNasc;
//getters e setters omitidos
}
13
JPA – Java Persistence API Exemplo de Entidade (usando mapeamentos
padrão)
import javax.persistence.*;
import java.util.*;
@Entity@Entity
public class Pessoa {
@Id@Id
@GeneratedValue@GeneratedValue
private int id;
private String nome;
@Temporal (TemporalType.DATE)@Temporal (TemporalType.DATE)
private Date dataNasc;
//getters e setters omitidos
}
14
JPA – Java Persistence API No código da aplicação que utiliza classes persistentes:
Criar uma fábrica de Gerenciador de Entidades:EntityManagerFactoryEntityManagerFactory emf =
Persistence.createEntityManagerFactoryPersistence.createEntityManagerFactory("unidade"); Criar um Gerenciador de Entidades através da fábrica:
EntityManagerEntityManager em = emf.createEntityManagercreateEntityManager(); Iniciar uma Transação (Necessário somente em alterações na base de dados):
em.getTransactiongetTransaction().beginbegin(); Criar uma Entidade:
Entidade e = newnew Entidade(); Persistir uma Entidade:
em.persistpersist(e); Localizar uma Entidade:
Entidade e = em.findfind(Entidade.class, chave); Sincronizar uma Entidade:
e = em.mergemerge(e); Eliminar uma Entidade:
em.removeremove(e); Encerrar uma Transação:
em.getTransactiongetTransaction().commitcommit();
15
JPA – Java Persistence API Interface EntityManager (alguns métodos)
void persistpersist(Object objeto)Persiste uma entidade, torna-a gerenciada pelo Gerenciador de Entidades. Qualquer alteração na entidade será refletida no banco de dados.
<T> T mergemerge(T entidade)Sincroniza os dados no banco de dados com os atributos da entidade. Retorna um objeto gerenciado(managed). Não pode ser usado em um objeto REMOVED.
void refreshrefresh(Object entidade)Sincroniza os atributos da entidade com os dados do banco de dados.
void removeremove(Object entidade)Remove uma entidade do banco de dados.
<T> T findfind(Class<T> classeEntidade, Object chavePrimária)Retorna uma entidade(MANAGED) através de sua chave primária. Retorna null caso a chave não seja encontrada.
16
JPA – Java Persistence API Query createQuerycreateQuery(String sql)
Cria uma consulta dinâmica. Query createNamedQuerycreateNamedQuery(String nomeConsulta)
Cria uma consulta nomeada. EntityTransaction getTransactiongetTransaction( )
Retorna a transação do EntityManager.
Interface EntityTransaction (alguns métodos) void beginbegin( )
Inicia uma transação. void commitcommit( )
Encerra uma transação, gravando quaisquer alterações no banco de dados.
void rollbackrollback( )Desfaz quaisquer alterações desde o início da transação.
17
JPA – Java Persistence API Exemplo de Aplicação JavaSE usando Oracle TopLink
Baixe o Oracle TopLink através do link:
http://www.oracle.com/technology/products/ias/toplink/jpa/
download.html
Coloque o arquivo baixado em uma pasta de trabalho e execute
o seguinte comando nesta pasta:
java -jar glassfish-persistence-installer-v2-bXX.jarjava -jar glassfish-persistence-installer-v2-bXX.jar Isto irá criar uma pasta chamada glassfish-persistenceglassfish-persistence
contendo o arquivo de licença, README e as bibliotecas TopLink
Essentials:
3RD-PARTY-LICENSE.txt
CDDLv1.0.txt
README
toplink-essentials-agent.jartoplink-essentials-agent.jar
toplink-essentials.jartoplink-essentials.jar
18
JPA – Java Persistence API Crie um projeto (Java5 ou superior) e adicione os arquivos .jar
mencionados anteriormente, no classpath, para que se possa utilizar o Oracle TopLink. Não esqueça de adicionar também o .jar do driver JDBC para o seu banco de dados.
Crie a classe persistente chamada PessoaPessoa descrita abaixo:
package modelo;import javax.persistence.*;import java.util.*;
@Entity@Entitypublic class Pessoa {
@Id@Id
@GeneratedValue (strategy=GenerationType.IDENTITY)@GeneratedValue (strategy=GenerationType.IDENTITY)private int id;private String nome;
@Temporal (TemporalType.DATE)@Temporal (TemporalType.DATE)private Date dataNasc;//getters e setters omitidos
}
19
JPA – Java Persistence API Crie o arquivo persistence.xmlpersistence.xml na pasta META-INFMETA-INF dentro da pasta srcsrc
em seu projeto.
<?xml version="1.0" encoding="UTF-8"?><persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="testeteste"><provider>
oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvideroracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider><class>modelo.Pessoamodelo.Pessoa</class><properties>
<property name="toplink.logging.level" value="INFOINFO" /><property name="toplink.jdbc.drivertoplink.jdbc.driver"
value="com.mysql.jdbc.Drivercom.mysql.jdbc.Driver" />
20
JPA – Java Persistence API<property name="toplink.jdbc.url"
value="jdbc:mysql://127.0.0.1:3306/unibanjdbc:mysql://127.0.0.1:3306/uniban" /><property name="toplink.jdbc.user" value="rootroot" /><property name="toplink.jdbc.password" value="adminadmin" /><property name="toplink.ddl-generation" value="create-tables" />
</properties></persistence-unit>
</persistence>
Crie o banco de dados de teste com o nome unibanuniban
21
JPA – Java Persistence API Inclusão - Inclusão - Crie a classe da aplicação chamada IncluiPessoaIncluiPessoa e a execute.
package negocio;import modelo.*;import javax.persistence.*;import java.util.*;public class IncluiPessoa { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Pessoa p = new Pessoa();Pessoa p = new Pessoa(); p.setNome("Breno");p.setNome("Breno");
GregorianCalendar data = GregorianCalendar data = new GregorianCalendar(2008, Calendar.FEBRUARY, 25);new GregorianCalendar(2008, Calendar.FEBRUARY, 25);
p.setDataNasc(data.getTime());p.setDataNasc(data.getTime()); em.persist(p); //Torna o objeto MANAGEDem.persist(p); //Torna o objeto MANAGED em.getTransaction().commit(); em.close(); emf.close(); System.out.println("id da pessoa persistida: " + p.getId()); }}
22
JPA – Java Persistence API Implantação da Aplicação (deploy) / Geração de jar executável.
Na pasta raiz do seu projeto, crie um arquivo texto chamado manifest.txt com o seguinte conteúdo:
Main-class: CriaPressoaClass-path: mysql-connector-java-5.0.6-bin.jar toplink-essentials.jar toplink-essentials-agent.jar
Obs.:Obs.: Deve haver um espaço em branco após os dois pontos de cada parâmetro; deve haver uma linha em branco no final do arquivo; os arquivos .jar devem ser separados por espaços em branco e devem estar numa única linha no arquivo.
No prompt de comando, na pasta raiz do seu projeto, digite a seguinte linha de comando:
jar cvfm teste.jar manifest.txt *.class model/*.class META-INF/*
Será gerado um arquivo chamado teste.jar que contém as classes da aplicação.
Copie os arquivos .jar do Oracle TopLink e o .jar do driver JDBC para a pasta onde estiver o arquivo teste.jar.
Para executar a aplicação, digite a seguinte linha de comando:java -jar teste.jar
23
JPA – Java Persistence API Automatização de deploy com o Apache Ant
Baixe o Ant (arquivo: apache-ant-1.7.0-bin.zip) do site: http://ant.apache.org
Descompacte o arquivo na pasta raiz do hd. Renomeie a pasta para "antant". Crie uma variável de ambiente chamada "ANT_HOMEANT_HOME"
contendo o caminho da pasta de instalação do ant:
"set ANT_HOME=c:\ant" Inclua o caminho "%ANT_HOME%\bin%ANT_HOME%\bin" no path do
sistema. Crie um arquivo build.xmlbuild.xml na pasta raiz do seu projeto
com o conteúdo a seguir.
24
JPA – Java Persistence API<?xml version="1.0" encoding="iso-8859-1" ?>
<project name= "teste" default= "implantaJar""implantaJar" >
<target name="implantaJar"name="implantaJar" depends="criaJar"> <copy file="${jarFile}" todir="${deployDir}"
overwrite="yes"/> </target>
<target name="criaJar"name="criaJar" depends="compila"> <jar destfile="${jarFile}" > <fileSet dir="." includes="*.class" /> <fileSet dir="./model" includes="*.class" />
<fileSet dir="./META-INF" includes="**" /> </jar> </target>
25
JPA – Java Persistence API <target name="compila"name="compila" depends="ambiente"> <javac srcdir="." destdir="."> <classpath path=" lib/toplink-essentials.jar" /> <classpath path=" lib/toplink-essentials-agent.jar" /> </javac> <javac srcdir="./model" destdir="./model"> <classpath path=" lib/toplink-essentials.jar" /> <classpath path=" lib/toplink-essentials-agent.jar" /> </javac> </target>
<target name="ambiente"name="ambiente" > <property name="jarFile" value= "./teste.jar""./teste.jar" /> <property name="deployDir" value="." /> </target> </project>
26
JPA – Java Persistence API Integrando o ANT com o Eclipse
Selecione o menu "Project"; Selecione "properties"; Selecione "Builders"; Clique em "new"; Escolha "Ant Build"; Em "Name Buildfile" clique em xxx e
selecione o arquivo de build criado anteriormente;
Com o build selecionado clique no botão "up" até que o "ant build" apareça em primeiro lugar na lista.
27
JPA – Java Persistence API Busca – Busca – Localiza uma entidade através da chave primária.package negocio;import modelo.*;import javax.persistence.*;public class BuscaPessoa { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); Pessoa p = em.find(Pessoa.class, 3); // Retorna um objeto MANAGEDPessoa p = em.find(Pessoa.class, 3); // Retorna um objeto MANAGED if (p != null) { System.out.println("ID: " + p.getId()); System.out.println("Nome: " + p.getNome()); //Objeto está MANAGED, porém, qualquer alteração NÃO será//Objeto está MANAGED, porém, qualquer alteração NÃO será //refletida no banco de dados, pois não há Transação.//refletida no banco de dados, pois não há Transação. p.setNome("Novo Nome"); } else { System.out.println("Pessoa não encontrada!"); } }}
28
JPA – Java Persistence API Alteração – Alteração – Localiza uma entidade através da chave primária e altera
seu estado.package negocio;import modelo.*;import javax.persistence.*;import java.util.*;public class AlteraPessoa { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Pessoa p = em.find(Pessoa.class, 1); Pessoa p = em.find(Pessoa.class, 1); //Retorna um objeto MANAGED//Retorna um objeto MANAGED
if (p != null) {if (p != null) {p.setNome("Novo Nome");p.setNome("Novo Nome");
p.setDataNasc(new Date());p.setDataNasc(new Date());System.out.println("id da pessoa alterada: " + p.getId());System.out.println("id da pessoa alterada: " + p.getId());
}} em.getTransaction().commit();
em.close(); emf.close();
}}
29
JPA – Java Persistence API Exclusão - Exclusão - Localiza uma entidade através da chave primária e a exclui.package negocio;import modelo.*;import javax.persistence.*;public class ExcluiPessoa {
public static void main(String[] args) { EntityManagerFactory emf =
Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Pessoa p = em.find(Pessoa.class, 8);Pessoa p = em.find(Pessoa.class, 8); if (p != null) {
em.remove(p); /*Objeto torna-se REMOVED, qualquer alteraçãoem.remove(p); /*Objeto torna-se REMOVED, qualquer alteração não será refletida no banco de dados.*/não será refletida no banco de dados.*/ System.out.println("Pessoa excluída: " + p.getId());
System.out.println(" " + p.getNome()); } else {
System.out.println("Pessoa não encontrada!"); } em.getTransaction().commit(); em.close(); emf.close();
}}
30
JPA – Java Persistence API Sincronização - Sincronização - Localiza uma entidade através da chave primária, encerra o
EntityManager, altera o estado da entidade e a sincroniza no banco de dados.
package negocio;import modelo.*;import javax.persistence.*;public class SincronizaPessoa {
public static void main(String[] args) {EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste");EntityManager em = emf.createEntityManager();Pessoa p = em.find(Pessoa.class, 9);Pessoa p = em.find(Pessoa.class, 9);em.close();em.close();if (p != null) {
System.out.println("Nome: " + p.getNome());p.setNome("Nicole");em = emf.createEntityManager();em = emf.createEntityManager();em.getTransaction().begin();em.getTransaction().begin();em.merge(p); //Sincroniza o estado da entidade no banco de dadosem.merge(p); //Sincroniza o estado da entidade no banco de dadosem.getTransaction().commit();em.getTransaction().commit();em.close();em.close();System.out.println("Novo Nome: " + p.getNome());
} else {System.out.println("Pessoa não encontrada!");
}}
}
31
JPA – Java Persistence API Mapeamento de Herança Hierárquica
Há três formas de se mapear uma hierarquia de herança:
Uma única tabela por hierarquia de classe (SINGLE_TABLESINGLE_TABLE)
Uma única tabela terá todas as propriedades de cada classe na
hierarquia.
Uma tabela por classe concreta (TABLE_PER_CLASSTABLE_PER_CLASS)
Cada classe terá uma tabela dedicada a ela, com todas as suas
propriedades e de sua superclasse mapeadas para essa tabela.
Uma tabela por subclasse (JOINEDJOINED)
Cada classe terá sua própria tabela. Cada tabela terá apenas as
propriedades definidas nessa classe particular. Essas tabelas não terão
propriedades de qualquer superclasse ou subclasse.
32
JPA – Java Persistence API
A anotação @Inheritance@Inheritance é utilizada na classe raiz
para definir a estratégia de persistência para o
relacionamento de herança através do atributo strategy.
Os valores de estratégia possíveis são: SINGLE_TABLESINGLE_TABLE,
JOINEDJOINED e TABLE_PER_CLASSTABLE_PER_CLASS
O valor default é SINGLE_TABLESINGLE_TABLE.
Informa-se a estratégia de persistência (@Inheritance)
apenas na classe raiz da hierarquia a não ser que se
queira uma estratégia diferente para as subclasses.
33
JPA – Java Persistence API Tabela única por hierarquia de classe (SINGLE_TABLESINGLE_TABLE)
Uma tabela do banco de dados representa todas as classes de uma dada
hierarquia. Nesse mapeamento, a tabela do banco de dados requer uma coluna
discriminadora, cujo nome é definido pela anotação @DiscriminatorColumn@DiscriminatorColumn.
Essa coluna é usada para identificar o tipo da entidade sendo armazenado em
uma linha da tabela. O tipo dessa coluna é definido através do atributo
“DiscriminatorTypeDiscriminatorType” que pode ser STRINGSTRING (valor padrão), CHARCHAR ou INTEGERINTEGER.
O valor dessa coluna é definido através da anotação @DiscriminatorValue@DiscriminatorValue.
Se omitir a anotação @DescriminatorColumn@DescriminatorColumn, o nome padrão para a coluna
discriminadora será “DTYPE”“DTYPE”.
Se omitir a anotação @DiscriminatorValue@DiscriminatorValue, o valor padrão da coluna será o
nome da entidade caso o tipo seja STRINGSTRING, para os outros tipos, o provedor de
persistência gera um valor automaticamente.
Nas subclasses, não é necessário nenhum mapeamento de herança, a não ser que
se queira alterar o valor do discriminador.
34
JPA – Java Persistence API Exemplo de superclasse:
package modelo;import javax.persistence.*;import java.util.* ;@Entity@Table(name = "Pessoa_Hierarquia")@Inheritance(strategy = InheritanceType.SINGLE_TABLE)@DiscriminatorColumn(name = "discriminator",
discriminatorType = DiscriminatorType.STRING)@DiscriminatorValue("PESSOA")public class Pessoa {
@Id@GeneratedValueprivate int id ;private String nome;@Temporal(TemporalType.DATE)private Date dataNasc;//getters e setters
}
35
JPA – Java Persistence API Exemplo de subclasse:
// Não esquecer de mapear o arquivo persistence.xml
package modelo;
import javax.persistence.*;
@Entity
@DiscriminatorValue("ALUNO")
public class Aluno extends Pessoa {
int ra;
String turma;
// getters e setters
}
36
JPA – Java Persistence API Vantagens
A estratégia de mapeamento SINGLE_TABLESINGLE_TABLE é a mais simples de
implementar e tem um desempenho melhor entre todas as
estratégias de herança. Há somente uma única tabela para se
administrar. O mecanismo de persistência não tem que fazer
nenhuma junção complexa, união ou subseleção ao carregar a
entidade, pois todos os dados estão em uma só tabela.
Desvantagens
Todas as colunas das propriedades de subclasse precisam ser
nuláveis. Portanto, se precisar definir quaisquer restrições NOT
NULL nessas colunas, não será permitido. Dependendo do tipo de
entidade, haverá colunas não-utilizadas. Essa estratégia não é
normalizada.
37
JPA – Java Persistence API Tabela por classe concreta (TABLE_PER_CLASSTABLE_PER_CLASS)
(Não suportado pelo Oracle TopLink v2)
Uma tabela de banco de dados é definida para cada classe concreta na hierarquia. Cada tabela tem colunas que representam suas propriedades e todas as propriedades de quaisquer super-classes.
Vantagens
A vantagem dessa estratégia em relação à SINGLE_TABLE é que se pode definir restrições nas propriedades das subclasses. Também pode ser mais fácil mapear o esquema de dados legado.
Desvantagens
Nessa estratégia, as tabelas não são normalizadas, pois possuem colunas redundantes. Uma forma de se implementar essa estratégia é utilizar o comando SQL Union, o que nem todos os bancos de dados suportam.
38
JPA – Java Persistence API Tabela por subclasse (JOINEDJOINED)
Cada subclasse tem sua própria tabela, mas essa tabela só contém as
propriedades definidas nessa classe particular. É semelhante à estratégia TABLE_PER_CLASSTABLE_PER_CLASS, exceto pelo esquema ser normalizado.
Nessa estratégia, deve haver uma coluna em cada tabela que possa ser utilizada para unir cada tabela. O nome dessa coluna é definido através da anotação @PrimaryKeyJoinColumn@PrimaryKeyJoinColumn pelo atributo “namename”. Se essa anotação for omitida, por padrão, é assumido o mesmo nome da coluna de chave primária da superclasse. Nas subclasses, o atributo “referencedColumnNamereferencedColumnName” da anotação
@PrimaryKeyJoinColum@PrimaryKeyJoinColum define a coluna da superclasse utilizada para realizar a junção.
Se omitir a anotação @DescriminatorColumn@DescriminatorColumn na superclasse, o nome padrão para a coluna discriminadora será “DTYPEDTYPE”.
39
JPA – Java Persistence API
Vantagens
Embora não seja tão rápido quanto a estratégia
SINGLE_TABLESINGLE_TABLE, consegue-se definir restrições NOT NULL em qualquer coluna de qualquer tabela, e seu modelo é normalizado. Esse mapeamento possui um melhor desempenho que a estratégia TABLE_PER_CLASSTABLE_PER_CLASS se SQL UNIONs não forem suportadas.
Desvantagens
Não possui um desempenho tão rápido quanto SINGLE_TABLESINGLE_TABLE.
40
JPA – Java Persistence API Consultas
As consultas são criadas usando-se tanto a linguagem de consulta EJB Query LanguageEJB Query Language (também chamada de JPA QLJPA QL) como a SQL nativa. A EJB QL é semelhante à SQL, só que orientada a objetos e portável para diferentes implementações de bancos de dados.
São executadas por meio da interface javax.persistence.Queryjavax.persistence.Query que é muito parecida com a interface java.sql.PreparedStatementjava.sql.PreparedStatement. Essa interface Query é obtida em tempo de execução a partir do gerenciador de entidade.
As consultas podem ser criadas dinamicamente em tempo de execução ou pré-declaradas por meio de anotações nas classes persistentes ou através de XML.
41
JPA – Java Persistence API Interface Query (javax.persistence.Query)
Alguns Métodos List getResultListgetResultList ( )
Executa uma consulta e retorna uma coleção de resultados.
Object getSingleResultgetSingleResult ( )
Executa uma consulta e retorna um único resultado. int executeUpdateexecuteUpdate ( )
Executa um comando de atualização(insert, update ou delete) e retorna o número de linhas afetadas no banco de dados.
Query setMaxResultssetMaxResults (int máximo)
Define o número máximo de entidades que deve ser retornado na consulta.
42
JPA – Java Persistence API Query setFirstResultsetFirstResult (int início)
Define o número da linha inicial que irá compor o resultado da consulta.
Query setParametersetParameter (String nome, Object valor)
Define o valor de um parâmetro através de seu nome. Query setParametersetParameter (String nome, Date valor, TemporalType
tipo)
Define o valor de um parâmetro do tipo data através de seu nome.
Query setParametersetParameter (int posição, Object valor)
Define o valor de um parâmetro através de sua posição. Query setParametersetParameter (int posição, Date valor, TemporalType
tipo)
Define o valor de um parâmetro do tipo data através de sua posição.
43
JPA – Java Persistence API Consultas Dinâmicas
São criadas pelo gerenciador de entidades através do método createQuerycreateQuery().
Consulta que retorna um único resultado:try {
Query consulta = em.createQuerycreateQuery( "Select a from Aluno a where a.ra = :ra:ra"); consulta.setParametersetParameter("rara", 123456789); Aluno a = (Aluno) consulta.getSingleResultgetSingleResult(); System.out.println("RA: " + a.getRa()); System.out.println("Nome: " + a.getNome());} catch(NoResultExceptionNoResultException ex) { System.out.println("Aluno não encontrado");} catch(NonUniqueResultExceptionNonUniqueResultException ex) { System.out.println("Mais que um resultado
encontrado");}
44
JPA – Java Persistence API Os parâmetros da consulta são ajustados através
do método setParametersetParameter( ) e podem ser indicados através de duas formas:
Identificados, utilizando-se :: (dois pontos) e um nome;
Query consulta = em.createQuerycreateQuery( "Select a from Aluno a where a.ra = :ra:ra and a.nome
= :nome:nome );consulta.setParametersetParameter("rara", 123456789);consulta.setParametersetParameter("nomenome", "Maria");
Sequenciados, utilizando-se ?? (interrogação) e um número sequencial.
Query consulta = em.createQuerycreateQuery( "Select a from Aluno a where a.ra = ?1?1 and a.nome = ?2?2 )
consulta.setParametersetParameter(11, 123456789);consulta.setParametersetParameter(22, "Maria");
45
JPA – Java Persistence APIpackage negocio;import modelo.*;
import javax.persistence.*;
public class BuscaPorRA { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); try { Query consulta = em.createQuery("Select a from Aluno a where Query consulta = em.createQuery("Select a from Aluno a where
a.ra = :ra");a.ra = :ra"); consulta.setParameter("ra", 123456789);consulta.setParameter("ra", 123456789); Aluno a = (Aluno)consulta.getSingleResult();Aluno a = (Aluno)consulta.getSingleResult(); System.out.println("RA: " + a.getRa()); System.out.println("Nome: " + a.getNome()); } catch(NoResultExceptionNoResultException ex) { System.out.println("Aluno não encontrado"); } catch(NonUniqueResultExceptionNonUniqueResultException ex) { System.out.println("Mais que um resultado encontrado"); } em.close(); emf.close(); }}
Consulta que retorna um único resultado
46
JPA – Java Persistence API Consulta que retorna os resultados em uma
java.util.List:
Query consulta = em.createQuerycreateQuery( "Select a from Aluno a where a.turma
= :turma:turma"); consulta.setParametersetParameter("turmaturma", "as05a.1"); ListList <Aluno>alunos = consulta.getResultListgetResultList();
if (!!alunos.isEmptyisEmpty()) { for (Aluno a : alunos) {
System.out.println("Nome: " + a.getNome()); } } else { System.out.println("Alunos não encontrados"); }
47
JPA – Java Persistence APIpackage negocio;import java.util.List;import modelo.*;import javax.persistence.*;public class ConsultaPorTurma { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager();
Query consulta = em.createQuery( "Select a from Aluno a where a.turma = :turma"); consulta.setParameter("turma", "as05a.1"); List <Aluno>alunos = consulta.getResultList(); if (!alunos.isEmpty()) { for (Aluno a : alunos) { System.out.println("Nome: " + a.getNome()); } } else { System.out.println("Alunos não encontrados"); }
em.close(); emf.close(); }}
Consulta que retorna umacoleção de resultados
48
JPA – Java Persistence API Consulta que utiliza um java.util.Date como parâmetro:
Query consulta = em.createQuerycreateQuery( "Select a from Aluno a where a.dataNasc = :data:data");
GregorianCalendar data = GregorianCalendar data = new GregorianCalendar(1971, Calendar.MARCH, 13);new GregorianCalendar(1971, Calendar.MARCH, 13);
consulta.setParametersetParameter("datadata", data.getTime(), TemporalType.DATETemporalType.DATE); ListList <Aluno>alunos = consulta.getResultListgetResultList();
if (!!alunos.isEmptyisEmpty()) { for (Aluno a : alunos) {
System.out.println("Nome: " + a.getNome()); } } else { System.out.println("Alunos não encontrados"); }
49
JPA – Java Persistence APIpackage negocio;
import java.util.*;import modelo.*;import javax.persistence.*;
public class ConsultaPorData {
public static void main(String[] args) {EntityManagerFactory emf = Persistence
.createEntityManagerFactory("teste");EntityManager em = emf.createEntityManager();
Query consulta = em.createQuery("Select a from Aluno a where a.dataNasc = :data");
GregorianCalendar data = new GregorianCalendar(2008, Calendar.FEBRUARY, 25);consulta.setParameter("data", data.getTime(), TemporalType.DATE);List<Aluno> alunos = consulta.getResultList();if (!alunos.isEmpty()) {
for (Aluno a : alunos) {System.out.println("Nome: " + a.getNome());
}} else {
System.out.println("Alunos não encontrados");}em.close();emf.close();
}}
Consulta utiliza um java.util.Date
como parâmetro
50
JPA – Java Persistence API Consulta com paginação de resultados:
public static List getAlunos(int maximo, int inicio) {Query consulta = em.createQuery("Select a from
Aluno a");return consulta.setMaxResultssetMaxResults(maximo).
setFirstResultsetFirstResult(inicio).getResultListgetResultList();
}
51
JPA – Java Persistence APIpackage negocio;import modelo.*;import javax.persistence.*;import java.util.List;public class ConsultaPaginada {
static EntityManagerFactory emf;static EntityManager em;
public static List getAlunos(int maximo, int inicio) {Query consulta = em.createQuery("Select a from Aluno a");return consulta.setMaxResults(maximo).
setFirstResult(inicio).getResultList();
}
Consulta com paginaçãode resultados
52
JPA – Java Persistence APIpublic static void main(String[] args) {
emf = Persistence.createEntityManagerFactory("teste");em = emf.createEntityManager();int inicio = 1, maximo = 3;int pagina = 1;List <Aluno> alunos = null;do {
alunos = getAlunos(maximo, inicio);if (!alunos.isEmpty()) {
System.out.println("Pág. " + pagina);for (Aluno a : alunos) {
System.out.println("Nome: " + a.getNome());}
}inicio += maximo;pagina++;
} while (!alunos.isEmpty());em.close();emf.close();
}}
53
JPA – Java Persistence API Consultas Nomeadas (Identificadas)
São consultas pré-definidas na classe da entidade e podem ser reutilizadas em diferentes pontos da sua aplicação, facilitando assim sua manutenção.
São declaradas através das anotações @NamedQueries@NamedQueries(define um array de consultas nomeadas) e @NamedQuery@NamedQuery(define uma consulta nomeada).
São criadas pelo gerenciador de entidades através do método createNamedQuerycreateNamedQuery().
@NamedQueries@NamedQueries({@NamedQuery@NamedQuery(name = "consultaPorRAconsultaPorRA",
query = "Select a from Aluno a where a.ra = :ra"),@NamedQuery@NamedQuery(name = "consultaPorTurmaconsultaPorTurma",
query = "Select a from Aluno a where a.turma = :turma")
})
Query consulta = em.createNamedQuerycreateNamedQuery("consultaPorTurmaconsultaPorTurma");
consulta.setParameter("turma", "as05a.1");
Na entidade
Na aplicação
54
JPA – Java Persistence APIpackage modelo;
import javax.persistence.*;
@NamedQueries @NamedQueries ( {@NamedQuery@NamedQuery (name = "buscaPorRA",
query = "Select a from Aluno a where a.ra = :ra"),@NamedQuery@NamedQuery (name = "consultaPorTurma",
query = "Select a from Aluno a where a.turma = :turma") } )
@Entity@Entitypublic class Aluno extends Pessoa {
int ra;String turma;// getters e setters
}
Utilização de Consulta NomeadaClasse da EntidadeClasse da Entidade
55
JPA – Java Persistence APIpackage negocio;import modelo.*;import javax.persistence.*;import java.util.List;public class ConsultaNomeada { public static void main(String[] args) { EntityManagerFactory emf =
Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); Query consulta = Query consulta =
em.createNamedQuery("consultaPorTurma");em.createNamedQuery("consultaPorTurma"); consulta.setParameter("turma", "as05a.1");consulta.setParameter("turma", "as05a.1");
List <Aluno>alunos = consulta.getResultListgetResultList(); if (!alunos.isEmpty()) { for (Aluno a : alunos) { System.out.println("Nome: " + a.getNome()); } } else { System.out.println("Alunos não encontrados"); }
em.close(); emf.close();
}}
Utilização de Consulta NomeadaClasse da AplicaçãoClasse da Aplicação
56
JPA – Java Persistence API Alterações em Lote
São criadas pelo gerenciador de entidades da mesma forma que as consultas.
Podem ser tanto dinâmicas como nomeadas. São executadas através do método
executeUpdateexecuteUpdate() que retorna o número de linhas afetadas.
Query alteracao = em.createQuerycreateQuery(
"UpdateUpdate Aluno set turma = :novaTurma:novaTurma");
alteracao.setParametersetParameter("novaTurmanovaTurma", "as05a.2");
intint qtdAlunos = alteracao.executeUpdateexecuteUpdate();
57
JPA – Java Persistence APIpackage negocio;
import javax.persistence.*;
public class TransfereTurma { public static void main(String[] args) { EntityManagerFactory emf =
Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); em.getTransaction().begin();
Query alteracao = em.createQuery( Query alteracao = em.createQuery( "Update Aluno set turma "Update Aluno set turma
= :novaTurma");= :novaTurma"); alteracao.setParameter("novaTurma", "as05a.2");alteracao.setParameter("novaTurma", "as05a.2"); int qtdAlunos = alteracao.executeUpdate();int qtdAlunos = alteracao.executeUpdate();
System.out.println(qtdAlunos + " Alunos transferidos de turma");
em.getTransaction().commit(); em.close(); emf.close(); }}
Alteração em lote
58
JPA – Java Persistence API Eventos de Retorno de Chamada
Através das anotações abaixo, pode-se definir métodos que serão executados em resposta a um evento do ciclo de vida de uma entidade.
@PrePersist@PrePersistDefine o método a ser executado logo após a uma chamada de EntityManager.persist().
@PostPersist@PostPersistDefine o método a ser executado após a inserção no banco de dados.
@PostLoad@PostLoadDefine o método a ser executado após a uma chamada de EntityManager.find(), EntityManager.refresh(), ou quando uma consulta EJB QL é executada.
59
JPA – Java Persistence API @PreUpdate@PreUpdate
Define o método a ser executado antes do estado de uma entidade ser sincronizado com o banco de dados.
@PostUpdate@PostUpdateDefine o método a ser executado após o estado de uma entidade ser sincronizado, isso ocorre na confirmação de uma transação, após uma chamada a EntityManager.flush() ou sempre que o contexto de persistência atualizar o banco de dados.
@PreRemove@PreRemoveDefine o método a ser executado após a uma chamada de EntityManager.remove().
@PostRemove@PostRemoveDefine o método a ser executado após a exclusão no banco de dados ser efetivada.
Pesquise também sobre Ouvintes de entidade.
60
JPA – Java Persistence APIpackage modelo;import java.io.*;import java.util.Date;import javax.persistence.*;
@Entitypublic class Aluno {
...@PrePersist@PrePersistvoid gravaLog() {
try {FileOutputStream fos = new FileOutputStream("log.txt", true);String linha = "Aluno " + getNome() + " gravado em " + new
Date() + "\n"; fos.write(linha.getBytes());fos.close();
} catch (IOException e) {e.printStackTrace();
}}
}
Exemplo de Arquivo de Log
61
JPA – Java Persistence API Exemplo de Aplicação Swing com
JPA
62
JPA – Java Persistence API Agregações
Em construção!!!