Slides Jpa - Novo

Preview:

Citation preview

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!!!