62
1 Curso de Linguagem Java Marcos Mendes 2010

Slides Jpa - Novo

Embed Size (px)

Citation preview

Page 1: Slides Jpa - Novo

1

Curso de Linguagem Java

Marcos Mendes

2010

Page 2: Slides Jpa - Novo

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

Page 3: Slides Jpa - Novo

3

JPA – Java Persistence API Arquitetura

Aplicação Java

Java Persistence API

Provedor JPA

API JDBC

Driver JDBC

BancoDe Dados

Page 4: Slides Jpa - Novo

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

Page 5: Slides Jpa - Novo

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.

Page 6: Slides Jpa - Novo

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

Page 7: Slides Jpa - Novo

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.

Page 8: Slides Jpa - Novo

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.

Page 9: Slides Jpa - Novo

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.

Page 10: Slides Jpa - Novo

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

Page 11: Slides Jpa - Novo

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.

Page 12: Slides Jpa - Novo

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

}

Page 13: Slides Jpa - Novo

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

}

Page 14: Slides Jpa - Novo

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();

Page 15: Slides Jpa - Novo

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.

Page 16: Slides Jpa - Novo

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.

Page 17: Slides Jpa - Novo

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

Page 18: Slides Jpa - Novo

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

}

Page 19: Slides Jpa - Novo

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" />

Page 20: Slides Jpa - Novo

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

Page 21: Slides Jpa - Novo

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()); }}

Page 22: Slides Jpa - Novo

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

Page 23: Slides Jpa - Novo

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.

Page 24: Slides Jpa - Novo

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>

Page 25: Slides Jpa - Novo

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>

Page 26: Slides Jpa - Novo

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.

Page 27: Slides Jpa - Novo

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!"); } }}

Page 28: Slides Jpa - Novo

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();

}}

Page 29: Slides Jpa - Novo

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();

}}

Page 30: Slides Jpa - Novo

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!");

}}

}

Page 31: Slides Jpa - Novo

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.

Page 32: Slides Jpa - Novo

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.

Page 33: Slides Jpa - Novo

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.

Page 34: Slides Jpa - Novo

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

}

Page 35: Slides Jpa - Novo

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

}

Page 36: Slides Jpa - Novo

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.

Page 37: Slides Jpa - Novo

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.

Page 38: Slides Jpa - Novo

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”.

Page 39: Slides Jpa - Novo

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.

Page 40: Slides Jpa - Novo

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.

Page 41: Slides Jpa - Novo

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.

Page 42: Slides Jpa - Novo

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.

Page 43: Slides Jpa - Novo

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");}

Page 44: Slides Jpa - Novo

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");

Page 45: Slides Jpa - Novo

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

Page 46: Slides Jpa - Novo

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"); }

Page 47: Slides Jpa - Novo

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

Page 48: Slides Jpa - Novo

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"); }

Page 49: Slides Jpa - Novo

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

Page 50: Slides Jpa - Novo

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();

}

Page 51: Slides Jpa - Novo

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

Page 52: Slides Jpa - Novo

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();

}}

Page 53: Slides Jpa - Novo

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

Page 54: Slides Jpa - Novo

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

Page 55: Slides Jpa - Novo

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

Page 56: Slides Jpa - Novo

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();

Page 57: Slides Jpa - Novo

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

Page 58: Slides Jpa - Novo

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.

Page 59: Slides Jpa - Novo

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.

Page 60: Slides Jpa - Novo

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

Page 61: Slides Jpa - Novo

61

JPA – Java Persistence API Exemplo de Aplicação Swing com

JPA

Page 62: Slides Jpa - Novo

62

JPA – Java Persistence API Agregações

Em construção!!!