You are on page 1of 72

Tpicos Avanados de Programao

2 Semestre - 2010

JPA - Java Persistence API (Beans de Entidade)


Referncia Bibliogrfica:
Enterprise JavaBeans 3.0 Bill Burke & Richard Monson Editora. Prentice Hall Desenvolvendo Aplicaes Web com JSP, Servlets, JSF, Hibernate, EJB 3 e Ajax Edson Gonalves Editora Cincia Moderna Revista JavaMagazine edies 39 e 44 Revista MundoJava edio 24 Pgina da Sun sobre a tecnologia JPA

http://java.sun.com/javaee/technologies/persistence.jsp

JPA Java Persistence API

Conceitos

Parte integrante da JavaEE 5 Disponvel a partir da Java5 Definida na JSR220 Enterprise JavaBeans 3.0 Padroniza o Mapeamento Objeto Relacional No depende de Container para funcionar Baseada no conceito de POJOs (Plain Old Java Object) Utiliza amplamente Annotations (Progamao Declarativa) Pacote javax.persistence
3

Introduo Persistncia e mapeamento O/R


A tecnologia de banco de dados relacionais existe h dcadas, e hoje os SGBDs so robustos e confiveis.Os principais problemas relacionados ao armazenamento e recuperao de dados j foram solucionados, e o investimento das empresas nesses sistemas tambm imenso, o que torna a sua utilizao uma regra. O uso dos bancos de dados relacionais, no entanto, traz alguns inconvenientes ao programador de linguagens orientadas a objetos como Java. As tecnologias OO e relacional so bastante diferentes, e seu uso conjunto normalmente implica em enfatizar uma tecnologia em sacrifcio da outra. Como os bancos de dados OO ainda esto muito menos disseminados que os bancos de dados relacionais, o desafio atual dos desenvolvedores unir dois mundos completamente distintos, utilizando a tecnologia relacional para armazenar objetos. O armazenamento de objetos de uma aplicao denominado persistncia de objetos. Essa tcnica permite que as instncias existentes no sistema sejam armazenadas e posteriormente recuperadas, conservando-se o seu estado mesmo aps a aplicao 4 ter sido finalizada.

Introduo Persistncia e mapeamento O/R


Desde as suas primeiras verses, a plataforma Java oferece acesso a bancos de dados atravs da API JDBC, que trabalha no mesmo nvel do banco, sendo o acesso s informaes armazenadas feito atravs de comandos SQL. Em muitos aspectos, a JDBC uma API de baixo nvel, que muitas vezes exige do desenvolvedor o conhecimento de banco de dados. Apesar de ser uma maneira eficiente de acessar dados em SGBDs relacionais, e a opo que normalmente oferece melhor performance, a JDBC oferece uma abstrao OO bastante limitada (trabalha-se com tabelas, registros e resultsets, ao invs de objetos). Para usar os recursos de bancos de dados relacionais em Java e ainda assim aproveitar os conceitos do paradigma OO, necessrio fazer o que se conhece como mapeamento objeto-relacional (ou simplesmente mapeamento O/R). No mapeamento O/R as classes e os atributos do sistema so mapeados para tabelas e campos/colunas, e a persistncia feita de forma transparente pela aplicao. Assim, objetos em memria so armazenados no banco, e objetos do banco so 5 trazidos para a memria sempre que necessrio.

Introduo Persistncia e mapeamento O/R


Com paradigmas to diferentes, diversas questes surgem durante o mapeamento: Como mapear herana? E agregao? Cada classe deve virar uma tabela? Como aproveitar os recursos do banco sem perder a abstrao de objetos? Para suprir essas necessidades, surgiram diversos frameworks e tecnologias de persistncia, a exemplo do Hibernate e do iBatis. Essas ferramentas facilitam o trabalho do desenvolvedor e aumentam sua produtividade, fornecendo poderosas APIs de manipulao de dados. Apesar de cada ferramenta possuir uma forma distinta de efetuar o mapeamento O/R, os conceitos so semelhantes e relativamente simples, baseando-se em POJOs (Plain Old Java Objects). O termo Plain Java Old Object (ou simplesmente POJO) - A traduo algo como velho e bom objeto Java e refere-se a objetos/classes Java simples, no atrelados a ferramentas ou frameworks.
6

A Java Persistence API


At o J2EE 1.4 a plataforma Java no possua uma forma simples de mapear objetos no banco de dados. A nica opo era a utilizao de Entity Beans, que exigem um container EJB e possuem uma complexidade razovel. Aplicaes cuja arquitetura no envolvia EJBs precisavam utilizar ferramentas no padronizadas como o Hibernate para fazer a persistncia, ou fazer a implementao de persistncia manualmente. A Java Persistence API, definida na JSR-220 (Enterprise JavaBeans,Version 3.0), padroniza o mapeamento objeto-relacional na plataforma Java. Apesar de descrita na especificao do novo EJB, a JPA no depende de um container para funcionar, sendo possvel usar e testar solues apenas com o Java SE2.

A Java Persistence API


A JPA uma especificao baseada no conceito de POJOs, que incorpora idias de renomados frameworks de persistncia para padronizar o mapeamento. O/R em Java. A API oferece uma soluo completa para mapeamento e persistncia de objetos: Um modo declarativo de descrever mapeamentos O/R Uma linguagem de consulta Um conjunto de ferramentas para manipular entidades Em se tratando de um padro do Java Community Process, a JPA traz diversos benefcios. O uso de um padro para a persistncia de objetos permite que diversos fabricantes trabalhem sobre os mesmos conceitos e que o desenvolvedor escolha a implementao de sua preferncia. A padronizao tambm traz outra importante vantagem: pode-se alternar entre implementaes de fabricantes distintos, que estejam em conformidade com a JSR-220, sem nenhum esforo adicional. Dessa forma, uma aplicao codificada de acordo com o novo padro ir funcionar com qualquer implementao da JPA, no havendo necessidade de se conhecer (a princpio) qual tecnologia ser utilizada para essa implementao.
8

JPA Java Persistence API

Entidades Os objetos persistentes so denominados Entities(Entidades) As Classes de Entidades devem atender a alguns requisitos: Ser anotadas com a anotao javax.persistence.Entity Possuir um identificador(chave primria) a no ser que seja uma subclasse. Possuir um construtor public ou protected sem parmetros (podem ter outros construtores). No podem ser declaradas como final. Mtodos ou variveis de instncia no podem ser declarados como final. Se forem passados como parmetro em uma chamada de mtodo remota, a classe precisa implementar a interface java.io.Serializable.
9

JPA Java Persistence API


Variveis de instncia devem ser declaradas como private, protected ou "default", e somente podem ser acessadas diretamente por mtodos da classe de entidade. Os clientes podem acessar o estado da entidade atravs de mtodos acessores ou mtodos de negcio. Campos Persistentes e Propriedades em uma Classe de Entidade O estado persistente de uma entidade pode ser acessado atravs das variveis de instncia ou atravs de mtodos acessores no estilo JavaBeans (getters e setters). O estado representado atravs dos seguintes tipos na linguagem Java:

Tipos Java primitivos Java.lang.String


10

JPA Java Persistence API

Outros tipos serializveis 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 serializveis definidos pelo usurio, byte[], Byte[], char[], Character[], tipos enumerados, outras entidades e/ou colees de entidades, classes "embeddable". Outras entidades e/ou Colees de entidades. Classes embutidas (Embeddable)

O mapeamento do estado das entidades feito com anotaes, ou nos campos persistentes, ou ento nos mtodos getters, nunca em ambos, em uma nica entidade.

11

JPA Java Persistence API

Unidade de Persistncia (Persistence Unit) Conjunto de classes mapeadas para um banco de dados

relacional que so gerenciadas por um Entity Manager. Esse


mapeamento feito atravs de um arquivo descritor de implantao chamado persistence.xml que gravado na

pasta META-INF e que pode conter a configurao de


vrias unidades de persistncia.

Contexto de Persistncia(Persistence Context)

Ambiente (sesso) que envolve o conjunto de instncias de


entidades gerenciadas pelo Entity Manager.

12

JPA Java Persistence API

Gerenciador de Entidades (Entity Manager)

javax.persistence.EntityManager

Servio que gerenciar o conjunto de entidades registradas dentro de um contexto. Monitorando as alteraes feitas nos objetos deste contexto de persistncia, gravando assim essas alteraes no banco de dados. Provedor de Persistncia (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 So alguns exemplos de fornecedores de provedores de persistncia:

Oracle TopLink, Hibernate, Kodo, Open JPA, etc.


13

JPA Java Persistence API

Arquitetura
Aplicao Java

Java Persistence API


Provedor JPA

API JDBC
Driver JDBC
Banco De Dados
14

JPA Java Persistence API

Ciclo de Vida / Estados de um objeto


clear( ) ou quando o EntityManager fechado

Objeto no existe
new find( )

DETACHED

NEW
merge( ) persist( )

MANAGED
remove( )

Garbage Collector
15

REMOVED

JPA - Mapeamento
As classes e interfaces da JPA esto localizadas no pacote javax.persistence. A API faz uso intensivo de anotaes (As anotaes surgiram da verso 5.0 do Java e esto presentes na maioria das APIs do novo JEE), por isso no necessrio criar descritores XML para cada uma das entidades da aplicao (Mesmo no sendo obrigatrio o uso de XML para descrever o mapeamento, ainda possvel utilizar essa opo. Um exemplo tpico o arquivo persistence.xml, que guarda as configuraes da unidade de persistncia. Uma entidade uma classe Java comum, rotulada atravs da anotao @Entity. No preciso implementar interfaces ou estender outras classes para tornar uma classe persistvel; a nica exigncia que a classe da entidade possua um construtor sem parmetros, pois a instanciao da classe feita por reflexo.
16

JPA Java Persistence API

Mapeamento Bsico de Entidades


feito com o uso de anotaes nas classes persistentes. @Entity Marca uma classe como entidade persistente. Esta
classe deve possuir um construtor sem parmetros. persistidos.

@Table Define o nome da Tabela onde os objetos sero

@Id Define o atributo que constitui a chave primria. @GeneratedValue Define um campo auto-incremento. @Column Define o nome da coluna onde o atributo ser salvo. @Temporal Fornece informaes adicionais ao provedor de
persistncia 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 Define que um atributo no ser salvo no banco


de dados.
17

JPA - Mapeamento
No cdigo a seguir a classe Pessoa representa uma entidade. O atributo cpf o identificador da entidade (chave primria), especificado atravs da anotao @Id: @Entity public class Pessoa { @Id private String cpf; }

18

JPA - Mapeamento
Grande parte da produtividade trazida pela JPA deve-se utilizao de valores default de mapeamento, que facilitam bastante o trabalho do desenvolvedor. Assim, o que no definido explicitamente assume a configurao padro da API. Por exemplo, por padro a JPA considera o nome da entidade o mesmo nome da tabela no banco de dados e o nome da propriedade o mesmo nome da coluna. No cdigo anterior, a entidade Pessoa ser salva na tabela PESSOA e a propriedade cpf na coluna CPF. Caso seja necessrio alterar a forma de mapeamento, devem-se utilizar as anotaes @Table e @Column, por exemplo: @Entity @Table(name=TB_PESSOA) public class Pessoa { @Id @Column(name=DS_CPF) private String cpf; }

19

JPA Mapeamento
Outro padro utilizado pelo JPA considerar todas as propriedades de uma entidade como persistentes (o mapeamento segue as regras descritas anteriormente). Caso seja desejvel excluir alguma propriedade do mapeamento (ex.: no caso de ela poder ser criada a partir de outras propriedades), basta marc-la com a anotao @Transient: @Entity public class Pessoa { @Id private String cpf; @Transient private String nomeCompleto; }
20

JPA Java Persistence API

Exemplo de Entidade
import javax.persistence.*;
@Entity @Table(name = "Aluno") public class Aluno { @Id @GeneratedValue (strategy=GenerationType.IDENTITY)
@Column(name = "id", nullable = false, columnDefinition = "integer")

private int id;


@Column(name = "nome", length = 50, nullable = false)

private String nome;


@Column(name = "ra")

private long ra; //getters e setters omitidos }


21

JPA Java Persistence API

Exemplo de Entidade
import javax.persistence.*; import java.util.*; @Entity @Table (name = "Pessoa") public class Pessoa { @Id

@GeneratedValue (strategy=GenerationType.IDENTITY)
@Column (name = "id", nullable = false, columnDefinition = "integer") private int id; @Column (name = "nome", length = 50, nullable = false) private String nome; @Column (name = "dataNasc") @Temporal (TemporalType.DATE) private Date dataNasc; //getters e setters omitidos

22

JPA Java Persistence API

Exemplo de Entidade (usando mapeamentos padro)


import javax.persistence.*;
@Entity public class Aluno { @Id @GeneratedValue private int id; private String nome; private long ra; //getters e setters omitidos }
23

JPA Java Persistence API

Exemplo de Entidade (usando mapeamentos padro)


import javax.persistence.*;

import java.util.*;
@Entity public class Pessoa { @Id @GeneratedValue private int id; private String nome;

@Temporal (TemporalType.DATE)
private Date dataNasc; //getters e setters omitidos } 24

JPA Java Persistence API

No cdigo da aplicao que utiliza classes persistentes:

Criar um Gerenciador de Entidades atravs de uma fbrica: EntityManagerFactory emf = Persistence.createEntityManagerFactory("unidade"); EntityManager em = emf.createEntityManager(); Iniciar uma Transao: em.getTransaction().begin(); Criar uma Entidade: Entidade e = new Entidade(); Persistir uma Entidade: em.persist(e); Localizar uma Entidade: Entidade e = em.find(Entidade.class, chave); Sincronizar uma Entidade: e = em.merge(e); Eliminar uma Entidade: em.remove(e); Encerrar uma Transao: em.getTransaction().commit(); 25

JPA Java Persistence API

Interface EntityManager

(alguns mtodos)

void persist(Object objeto)


Persiste uma entidade, torna-a gerenciada pelo Gerenciador de Entidades. Qualquer alterao na entidade ser refletida no banco de dados.

<T> T merge(T entidade)


Sincroniza os dados no banco de dados com os atributos da entidade. Retorna um objeto gerenciado(managed). No pode ser usado em um objeto REMOVED.

void refresh(Object entidade)


Sincroniza os atributos na entidade com os dados do banco de dados.

void remove(Object entidade)


Remove uma entidade do banco de dados.

<T> T find(Class<T> classeEntidade, Object chavePrimria)


Retorna uma entidade(MANAGED) atravs de sua chave primria. Retorna null caso a chave no seja encontrada.
26

JPA Java Persistence API

Query createQuery(String sql)


Cria uma consulta dinmica.

Query createNamedQuery(String nomeConsulta)


Cria uma consulta nomeada.

EntityTransaction getTransaction( )
Retorna a transao do EntityManager.

Interface EntityManager

(alguns mtodos)

void begin( )
Inicia uma transao.

void commit( )
Encerra uma transao, gravando quaisquer alteraes no banco de dados.

void rollback( )
Desfaz quaisquer alteraes desde o incio da transao.
27

JPA Java Persistence API

Exemplo de Aplicao JavaSE usando Oracle TopLink

Baixe o Oracle TopLink atravs 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.jar Isto ir criar uma pasta chamada glassfish-persistence contendo o arquivo de licena, README e as bibliotecas TopLink Essentials: 3RD-PARTY-LICENSE.txt CDDLv1.0.txt README toplink-essentials-agent.jar toplink-essentials.jar

28

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. No esquea de adicionar tambm o .jar do driver JDBC. Crie a classe persistente chamada Aluno descrita abaixo: package modelo; import javax.persistence.*; @Entity public class Aluno { @Id @GeneratedValue (strategy=GenerationType.IDENTITY) private int id; private String nome; private long ra; private double ms1; private double ms2; //getters e setters omitidos }
29

JPA Java Persistence API

Crie o arquivo persistence.xml na pasta META-INF 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="teste"> <provider> oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider </provider> <class>modelo.Aluno</class> <properties> <property name="toplink.logging.level" value="INFO" /> <property name="toplink.jdbc.driver" value="com.mysql.jdbc.Driver" />
30

JPA Java Persistence API


<property name="toplink.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/uniban" /> <property name="toplink.jdbc.user" value="root" /> <property name="toplink.jdbc.password" value="admin" /> <property name="toplink.ddl-generation" value="create-tables" /> </properties> </persistence-unit> </persistence> Crie o banco de dados de teste com o nome uniban

31

JPA Java Persistence API

Incluso - Crie a classe da aplicao chamada CriaAluno e a execute.

package negocio;

import modelo.*; import javax.persistence.*; public class CriaAluno { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Aluno a = new Aluno(); a.setNome("Maria"); a.setRa(123456789); a.setMs1(5.5); a.setMs2(4.5); em.persist(a); //Torna o objeto MANAGED em.getTransaction().commit(); em.close(); emf.close(); System.out.println("id do aluno persistido: " + a.getId()); } } 32

JPA Java Persistence API

Implantao da Aplicao.

Na pasta raiz do seu projeto, crie um arquivo texto chamado manifest.txt com o seguinte contedo:

Main-class: CriaAluno Class-path: mysql-connector-java-5.0.6-bin.jar toplink-essentials.jar toplink-essentials-agent.jar


Obs.: Deve haver um espao em branco aps os dois pontos de cada parmetro; deve haver uma linha em branco no final do arquivo; os arquivos .jar devem ser separados por espaos 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 contm as classes da aplicao. 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 aplicao, digite a seguinte linha de comando: java -jar teste.jar
33

JPA Java Persistence API

Automatizao 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 "ant".

Crie uma varivel de ambiente chamada "ANT_HOME" contendo o caminho da pasta de instalao do ant:
"set ANT_HOME=c:\ant"

Inclua o caminho "%ANT_HOME%\bin" no path do sistema.


Crie um arquivo build.xml na pasta raiz do seu projeto com o contedo a seguir.
34

JPA Java Persistence API


<?xml version="1.0" encoding="iso-8859-1" ?> <project name= "teste" default= "implantaJar" > <target name="implantaJar" depends="criaJar"> <copy file="${jarFile}" todir="${deployDir}" overwrite="yes"/> </target> <target name="criaJar" depends="compila"> <jar destfile="${jarFile}" > <fileSet dir="." includes="*.class" /> <fileSet dir="./model" includes="*.class" /> <fileSet dir="./META-INF" includes="**" /> </jar> </target>

35

JPA Java Persistence API


<target 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" > <property name="jarFile" value= "./teste.jar" /> <property name="deployDir" value="." /> </target> </project>
36

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 boto "up" at que o "ant build" aparea em primeiro lugar na lista.
37

JPA Java Persistence API


Busca Localiza uma entidade atravs da chave primria. package negocio; import modelo.*; import javax.persistence.*; public class BuscaAluno { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); Aluno a = em.find(Aluno.class, 3); // Retorna um objeto MANAGED if (a != null) { System.out.println("RA: " + a.getRa()); System.out.println("Nome: " + a.getNome()); //Objeto est MANAGED, porm, qualquer alterao NO ser //refletida no banco de dados, pois no h Transao. a.setNome("Novo Nome"); } else { System.out.println("Aluno no encontrado"); } } }

38

JPA Java Persistence API


Alterao Localiza uma entidade atravs da chave primria e altera seu estado. package negocio; import modelo.*; import javax.persistence.*; public class AlteraAluno { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Aluno a = em.find(Aluno.class, 1); //Retorna um objeto MANAGED if (a != null) { a.setNome("Novo Nome"); a.setRa(987654321); a.setMs1(2.5); a.setMs2(3.5); System.out.println("id do aluno alterado: " + a.getId()); } em.getTransaction().commit(); em.close(); emf.close(); } } 39

JPA Java Persistence API

Excluso - Localiza uma entidade atravs da chave primria e a exclui.

package negocio; import modelo.*; import javax.persistence.*; public class ExcluiAluno { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Aluno a = em.find(Aluno.class, 8); if (a != null) { em.remove(a); /*Objeto torna-se REMOVED, qualquer alterao no ser refletida no banco de dados.*/ System.out.println("Aluno excludo: " + a.getId()); System.out.println(" " + a.getNome()); } else { System.out.println("Aluno no encontrado"); } em.getTransaction().commit(); em.close(); emf.close(); } }

40

JPA Java Persistence API

package negocio; import modelo.*; import javax.persistence.*; public class SincronizaAluno { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager(); Aluno a = em.find(Aluno.class, 9); em.close(); if (a != null) { System.out.println("Nome: " + a.getNome()); a = mudaDados(a); em = emf.createEntityManager(); em.getTransaction().begin(); em.merge(a); //Sincroniza o estado da entidade no banco de dados em.getTransaction().commit(); System.out.println("Novo Nome: " + a.getNome()); } else { System.out.println("Aluno no encontrado"); } } private static Aluno mudaDados(Aluno a) { a.setNome("Juliana"); return a; } }

Sincronizao - Localiza uma entidade atravs da chave primria, encerra o EntityManager, altera o estado da entidade e a sincroniza no banco de dados.

41

JPA Java Persistence API

Mapeamento de Herana Hierrquica


H trs formas de se mapear uma hierarquia de herana:

Uma nica tabela por hierarquia de classe (SINGLE_TABLE)


Uma nica tabela ter todas as propriedades de cada classe na hierarquia.

Uma tabela por classe concreta (TABLE_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 (JOINED)


Cada classe ter sua prpria tabela. Cada tabela ter apenas as propriedades definidas nessa classe particular. Essas tabelas no tero propriedades de qualquer superclasse ou subclasse. 42

JPA Java Persistence API


A anotao @Inheritance utilizada na classe raiz para definir a estratgia de persistncia para o relacionamento de herana

atravs do atributo strategy.


Os valores de estratgia possveis so: SINGLE_TABLE, JOINED e TABLE_PER_CLASS

O valor default SINGLE_TABLE.


Informa-se a estratgia de persistncia (@Inheritance) apenas na classe raiz da hierarquia a no ser que se queira uma estratgia diferente para as subclasses.

43

JPA Java Persistence API

Tabela nica por hierarquia de classe (SINGLE_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 anotao @DiscriminatorColumn. Essa coluna usada para identificar o tipo da entidade sendo armazenado em uma linha da tabela. O tipo dessa coluna definido atravs do atributo DiscriminatorType que pode ser STRING (valor padro), CHAR ou INTEGER. O valor dessa coluna definido atravs da anotao @DiscriminatorValue. Se omitir a anotao @DescriminatorColumn, o nome padro para a coluna discriminadora ser DTYPE. Se omitir a anotao @DiscriminatorValue, o valor padro da coluna ser o nome da

entidade caso o tipo seja STRING, para os outros tipos, o provedor de persistncia gera
um valor automaticamente. Nas subclasses, no necessrio nenhum mapeamento de herana, a no ser que se queira alterar o valor do discriminador.

44

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 @GeneratedValue private int id ; private String nome; @Temporal(TemporalType.DATE) private Date dataNasc; //getters e setters }

45

JPA Java Persistence API

Exemplo de subclasse:
// No 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 }

46

JPA Java Persistence API

Vantagens
A estratgia de mapeamento SINGLE_TABLE a mais simples de

implementar e tem um desempenho melhor entre todas as estratgias de


herana. H somente uma nica tabela para se administrar. O mecanismo de persistncia no tem que fazer nenhuma juno complexa, unio ou subseleo ao carregar a entidade, pois todos os dados esto em uma s tabela.

Desvantagens
Todas as colunas das propriedades de subclasse precisam ser nulveis. Portanto, se precisar definir quaisquer restries NOT NULL nessas colunas, no ser permitido. Dependendo do tipo de entidade, haver colunas noutilizadas. Essa estratgia no normalizada. 47

JPA Java Persistence API

Tabela por classe concreta (TABLE_PER_CLASS)


(No 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 estratgia em relao SINGLE_TABLE que se pode definir restries nas propriedades das subclasses. Tambm pode ser mais fcil mapear o esquema de dados legado.

Desvantagens
Nessa estratgia, as tabelas no so normalizadas, pois possuem colunas redundantes. Uma forma de se implementar essa estratgia utilizar o comando SQL Union, o que nem todos os bancos de dados suportam.

48

JPA Java Persistence API

Tabela por subclasse (JOINED)


Cada subclasse tem sua prpria tabela, mas essa tabela s contm as

propriedades definidas nessa classe particular. semelhante estratgia TABLE_PER_CLASS, exceto pelo esquema ser normalizado.
Nessa estratgia, deve haver uma coluna em cada tabela que possa ser utilizada para unir cada tabela. O nome dessa coluna definido atravs da anotao @PrimaryKeyJoinColumn pelo atributo name. Se essa anotao for omitida, por padro, assumido o mesmo nome da coluna de chave primria da superclasse. Nas subclasses, o atributo referencedColumnName da anotao @PrimaryKeyJoinColum define a coluna da superclasse utilizada para realizar a juno. Se omitir a anotao @DescriminatorColumn na superclasse, o nome padro para a coluna discriminadora ser DTYPE.

49

JPA Java Persistence API

Vantagens
Embora no seja to rpido quanto a estratgia SINGLE_TABLE, consegue-se definir restries NOT NULL em qualquer coluna de qualquer tabela, e seu modelo normalizado. Esse mapeamento possui um melhor desempenho que a estratgia TABLE_PER_CLASS se SQL UNIONs no forem suportadas.

Desvantagens
No possui um desempenho to rpido quanto SINGLE_TABLE.
50

JPA Java Persistence API

Consultas
As consultas so criadas usando-se tanto a linguagem de consulta EJB Query Language (tambm chamada de JPA QL) como a SQL nativa. A EJB QL semelhante SQL, s que orientada a objetos e portvel para diferentes implementaes de bancos de dados. So executadas por meio da interface javax.persistence.Query que muito parecida com a interface java.sql.PreparedStatement. Essa interface Query obtida em tempo de execuo a partir do gerenciador de entidade. As consultas podem ser criadas dinamicamente em tempo de execuo ou pr-declaradas por meio de anotaes nas classes persistentes ou atravs de XML.
51

JPA Java Persistence API

Interface Query

(javax.persistence.Query)

Alguns Mtodos

List getResultList ( ) Executa uma consulta e retorna uma coleo de resultados. Object getSingleResult ( ) Executa uma consulta e retorna um nico resultado. int executeUpdate ( ) Executa um comando de atualizao(insert, update ou delete) e retorna o nmero de linhas afetadas no banco de dados. Query setMaxResults (int mximo) Define o nmero mximo de entidades que deve ser retornado na consulta.
52

JPA Java Persistence API

Query setFirstResult (int incio) Define o nmero da linha inicial que ir compor o resultado da consulta. void setParameter (String nome, Object valor) Define o valor de um parmetro atravs de seu nome. Query setParameter (String nome, Date valor, TemporalType tipo) Define o valor de um parmetro do tipo data atravs de seu nome. Query setParameter (int posio, Object valor) Define o valor de um parmetro atravs de sua posio. Query setParameter (int posio, Date valor, TemporalType tipo) Define o valor de um parmetro do tipo data atravs de sua posio.
53

JPA Java Persistence API

Consultas Dinmicas
So criadas pelo gerenciador de entidades atravs do mtodo createQuery().

Consulta que retorna um nico resultado:

try { Query consulta = em.createQuery( "Select a from Aluno a where a.ra = :ra"); consulta.setParameter("ra", 123456789); Aluno a = (Aluno) consulta.getSingleResult(); System.out.println("RA: " + a.getRa()); System.out.println("Nome: " + a.getNome()); } catch(NoResultException ex) { System.out.println("Aluno no encontrado"); } catch(NonUniqueResultException ex) { System.out.println("Mais que um resultado encontrado"); }
54

JPA Java Persistence API

Os parmetros da consulta so ajustados atravs do mtodo setParameter( ) e podem ser indicados atravs de duas formas:

Identificados, utilizando-se : (dois pontos) e um nome;

Query consulta = em.createQuery( "Select a from Aluno a where a.ra = :ra and a.nome = :nome ); consulta.setParameter("ra", 123456789); consulta.setParameter("nome", "Maria");

Seqenciados, utilizando-se ? (interrogao) e um nmero sequencial.

Query consulta = em.createQuery( "Select a from Aluno a where a.ra = ?1 and a.nome = ?2 ) consulta.setParameter(1, 123456789); consulta.setParameter(2, "Maria");
55

JPA Java Persistence API


package negocio; import modelo.*; import javax.persistence.*;

Consulta que retorna um nico resultado

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 a.ra = :ra"); consulta.setParameter("ra", 123456789); Aluno a = (Aluno)consulta.getSingleResult(); System.out.println("RA: " + a.getRa()); System.out.println("Nome: " + a.getNome()); } catch(NoResultException ex) { System.out.println("Aluno no encontrado"); } catch(NonUniqueResultException ex) { System.out.println("Mais que um resultado encontrado"); } em.close(); emf.close(); } }

56

JPA Java Persistence API

Consulta que retorna os resultados em uma java.util.List:

Query consulta = em.createQuery( "Select a from Aluno a where a.ms1 > :media"); consulta.setParameter("media", 5); List <Aluno>alunos = consulta.getResultList(); if (!alunos.isEmpty()) { for (Aluno a : alunos) { System.out.println("Nome: " + a.getNome()); } } else { System.out.println("Alunos no encontrados"); }
57

JPA Java Persistence API


package negocio; Consulta que retorna uma import java.util.List; coleo de resultados import modelo.*; import javax.persistence.*; public class ConsultaPorMedia { 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.ms1 > :media"); consulta.setParameter("media", 5); List <Aluno>alunos = consulta.getResultList(); if (!alunos.isEmpty()) { for (Aluno a : alunos) { System.out.println("Nome: " + a.getNome()); } } else { System.out.println("Alunos no encontrados"); } em.close(); emf.close();

58

JPA Java Persistence API


package 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 no encontrados"); } em.close(); emf.close(); } }

Consulta que retorna uma coleo de resultados

59

JPA Java Persistence API

Consulta que utiliza um java.util.Date como parmetro:

Query consulta = em.createQuery( "Select a from Aluno a where a.DataMatricula = :data"); consulta.setParameter("data", new java.util.Date, 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 no encontrados"); }

60

JPA Java Persistence API


package 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 no encontrados"); } em.close(); emf.close();

Consulta utiliza um

java.util.Date como parmetro

61

JPA Java Persistence API

Consulta com paginao de resultados:

public static List getAlunos(int maximo, int inicio) { Query consulta = em.createQuery("Select a from Aluno a"); return consulta.setMaxResults(maximo). setFirstResult(inicio). getResultList(); }

62

JPA Java Persistence API


package negocio; import modelo.*; import javax.persistence.*; import java.util.List; public class ConsultaPaginada { static EntityManagerFactory emf; static EntityManager em;

Consulta com paginao de resultados

public static List getAlunos(int maximo, int inicio) { Query consulta = em.createQuery("Select a from Aluno a"); return consulta.setMaxResults(maximo). setFirstResult(inicio). getResultList(); }

63

JPA Java Persistence API


public 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("Pg. " + pagina); for (Aluno a : alunos) { System.out.println("Nome: " + a.getNome()); } } inicio += maximo; pagina++; } while (!alunos.isEmpty()); em.close(); emf.close(); } } 64

JPA Java Persistence API

Consultas Nomeadas (Identificadas)

So consultas pr-definidas na classe da entidade e podem ser reutilizadas em diferentes pontos da sua aplicao, facilitando assim sua manuteno. So declaradas atravs das anotaes @NamedQueries(define um array de consultas nomeadas) e @NamedQuery(define uma consulta nomeada). So criadas pelo gerenciador de entidades atravs do mtodo createNamedQuery().

Na entidade

Na aplicao

@NamedQueries({ @NamedQuery(name = "consultaPorRA", query = "Select a from Aluno a where a.ra = :ra"), @NamedQuery(name = "consultaPorMedia", query = "Select a from Aluno a where a.ms1 > :media") })

Query consulta = em.createNamedQuery("consultaPorMedia"); consulta.setParameter("media", 5);


65

JPA Java Persistence API


package modelo; import javax.persistence.*;

Utilizao de Consulta Nomeada Classe da Entidade

@NamedQueries ( { @NamedQuery (name = "buscaPorRA", query = "Select a from Aluno a where a.ra = :ra"), @NamedQuery (name = "consultaPorTurma", query = "Select a from Aluno a where a.turma = :turma") } )
@Entity public class Aluno extends Pessoa { int ra; String turma; // getters e setters }

66

JPA Java Persistence API


Utilizao de package negocio; import modelo.*; Consulta Nomeada import javax.persistence.*; Classe da Aplicao import java.util.List; public class ConsultaNomeada { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste"); EntityManager em = emf.createEntityManager();
Query consulta = em.createNamedQuery("consultaPorMedia"); consulta.setParameter("media", 5); List <Aluno>alunos = consulta.getResultList(); if (!alunos.isEmpty()) { for (Aluno a : alunos) { System.out.println("Nome: " + a.getNome()); } } else { System.out.println("Alunos no encontrados"); } em.close(); emf.close(); 67

JPA Java Persistence API

Alteraes em Lote

So criadas pelo gerenciador de entidades da mesma forma que as consultas. Podem ser tanto dinmicas como nomeadas. So executadas atravs do mtodo executeUpdate() que retorna o nmero de linhas afetadas.

Query alteracao = em.createQuery(

"Update Aluno set ms1 = ms1 + :bonus");


alteracao.setParameter("bonus", 0.5); int qtdAlunos = alteracao.executeUpdate();
68

JPA Java Persistence API


package negocio; import javax.persistence.*;

Alterao em lote

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( "Update Aluno set turma = :novaTurma"); alteracao.setParameter("novaTurma", "as05a.2"); int qtdAlunos = alteracao.executeUpdate(); System.out.println(qtdAlunos + " Alunos transferidos de turma");
em.getTransaction().commit(); em.close(); emf.close();

69

JPA Java Persistence API

Eventos de Retorno de Chamada


Atravs das anotaes abaixo, pode-se definir mtodos que sero executados em resposta a um evento do ciclo de vida de uma entidade.

@PrePersist
Define o mtodo a ser executado logo aps a uma chamada de EntityManager.persist().

@PostPersist
Define o mtodo a ser executado aps a insero no banco de dados.

@PostLoad
Define o mtodo a ser executado aps a uma chamada de EntityManager.find(), EntityManager.refresh(), ou quando uma consulta EJB QL executada.
70

JPA Java Persistence API

@PreUpdate
Define o mtodo a ser executado antes do estado de uma entidade ser sincronizado com o banco de dados.

@PostUpdate
Define o mtodo a ser executado aps o estado de uma entidade ser sincronizado, isso ocorre na confirmao de uma transao, aps uma chamada a EntityManager.flush() ou sempre que o contexto de persistncia atualizar o banco de dados.

@PreRemove
Define o mtodo a ser executado aps a uma chamada de EntityManager.remove().

@PostRemove
Define o mtodo a ser executado aps a excluso no banco de dados ser efetivada.

Pesquise tambm sobre Ouvintes de entidade.


71

JPA Java Persistence API


package modelo; import java.io.*; import java.util.Date; import javax.persistence.*;

Exemplo de Arquivo de Log

@Entity public class Aluno { ... @PrePersist void prePersist() { try { FileOutputStream fos = new FileOutputStream("log.txt", true); String linha = "Aluno " + getNome() + " gravado em " + new Date() + "\n"; fos.write(linha.getBytes()); fos.close(); fos.close(); } catch (IOException e) { e.printStackTrace(); } } } 72