Sei sulla pagina 1di 12

Persistncia com EJB 3.

0 Java Persistence API (JPA)


Fabricio Santana, Gabriel Santana, Guilherme Ribeiro, Jocimar Ferreira

{fabricio, santana, gar, jocimar}@dcc.ufba.br

Abstract. This Paper describes the main characteristics of the new persistence API in EJB 3.0, named Java Persistence API (JPA). It is showed the use of entities, included the use of inheritance, polymorphism and relationships. Finally, the language EJB-QL is introduced. Resumo. Este artigo descreve as principais caractersticas da nova API de persistncia em EJB 3.0, chamada Java Persistence API (JPA). demonstrado o uso de entidades, inclusive com herana, polimorfismo e relacionamentos. Por fim introduzida a linguagem EJB-QL.

1. Introduo
No intuito de se criar uma arquitetura de objetos distribudos na internet, que pudesse oferecer uma infra-estrutura para o desenvolvimento de aplicaes distribudas, a Sun definiu a especificao EJB (Enterprise JavaBeans) como parte da plataforma J2EE(JAVA 2 Enterprise Edition). O EJB oferece para o desenvolvedor os servios inerentes aos ambientes distribudos como: gerenciamento de transaes (trata os acessos simultneos de usurios diferentes a um mesmo registro de uma tabela), segurana (controle sobre o tipo de acesso que os usurios possuem sobre os dados) , gerenciamento de recursos, dentre outros. Desta forma, a especificao EJB permite que o desenvolvedor se atenha s regras de negcio, facilitando e otimizando o desenvolvimento de aplicaes distribudas. Um mecanismo de persistncia est includa na especificao de EJB. Anteriormente eram utilizadas as Entity Beans, mas elas tinham um problema de performance, alm de outras limitaes. Por isso, para EJB 3.0 foi especificada uma nova API de persistncia, a Java Persistence API (JPA), que adiciona uma nova dimenso na especificao de EJB que anteriormente estava em falta. Ele traz todas as vantagens da orientao a objetos, enquanto persiste os dados de forma automtica, implicitamente. O JPA utiliza mapeamento objeto-relacional, trabalhando com entidades POJO (Plain Old Java Objects), que simplificam bastante o processo de desenvolvimento.

2. Definies EJB
2.1. Container EJB A execuo de aplicaes distribudas que utilizam o EJB depende da existncia de um container para o Enterprise JavaBeans. Um container para EJB um software que prov o ambiente necessrio para a utilizao dos componentes bsicos da arquitetura Enterprise JavaBeans. Portanto, um container EJB um pedao de software que implementa a especificao Enterprise JavaBeans, esta sendo disponibilizada pela Sun.

2.2. Beans Beans so componentes Java EE que executam a especificao Enterprise Java Beans. Existem trs tipos de beans para a arquitetura EJB: Session Beans, Message Driven Beans (MDB) e Entity Beans. Os Sessions Beans so responsveis por armazenar e executar as regras de negcios solicitados diretamente pelos clientes. Sendo que estes beans no possuem dados persistentes e seu ciclo de vida est vinculada sesso criada pelo cliente, ou seja, quando a sesso cliente fechada o session bean destrudo. O Message Driven Bean (MDB) um bean que permite o processamento de mensagens assncronas entre as aplicaes Java EE. Esse tipo de bean muito semelhante ao session bean, porm no pode ser acessado diretamente pelo cliente. Os Entity Beans so componentes que representam em memria os dados que esto persistidos em um meio de armazenamento.

3. Java Persistence a Nova API de Persistncia


At a verso anterior de EJB, o programador precisava usar as Entity Beans para lidar com a persistncia. No entanto existe um problema com esta tecnologia: ela bastante pesada. A sua performance baixa, e ela pode consumir bastante recursos dos servidores. Enquanto isso, tecnologias alternativas de persistncia surgiram, usando entidades no estilo POJO, isto , entidades que podem ser tratadas como objetos comuns (POJO Plain Old Java Object). Tratar dados como objetos tem vantagens, como uma maior facilidade de manipulao e gerenciamento, alm de serem representados de forma mais compacta. Por isso houve uma demanda por uma tecnologia leve e que suportasse esta tecnologia. A resposta a nova API, Java Persistence. Ela uma especificao separada da EJB, e no est presa a ela. Isto , no necessrio us-la com EJB, nem mesmo com Java EE. Ela pode ser usada em um ambiente Java SE. A Java Persistence API (JPA) trabalha com mapeamento objeto-relacional. 3.1. Entidades (Entities) A especificao Java Persistence utiliza a definio de entidades para representar os dados. Uma entidade um objeto Java que pode ser persistido em um banco de dados. Os dados so representados pelos atributos do objeto entidade, e ele pode ter mtodos associados. Uma entidade no pode ser remotamente acessvel. Isso significa que um cliente no pode acessar um banco de dados em um servidor. O servidor que deve prover os dados para o cliente, se necessrio, tanto como um objeto inteiro como de forma fragmentada, de forma a revelar somente alguns dados. 3.2. Classes Entidades Um exemplo simples de uma classe entidade est especificado abaixo, no Cdigo 1.

package examples.entity.intro; import javax.persistence.Entity; import javax.persistence.Id; @Entity public class Cliente extends Pessoa{ //codigo eh a chave primaria @Id public int codigo;

public Cliente(){ //um gerador de chave primaria codigo = (int) System.nanoTime(); } public setNome(String pNome){ nome=pNome; } /*Mais metodos setters e getters*/ }
Cdigo 1. Uma entidade simples

A classe Cliente extende Pessoa, que passa dados pessoais, como CPF, nome, endereo, telefone, idade e sexo. Mapeando esta classe, teremos uma tabela CLIENTE com os campos CODIGO, NOME, ENDERECO, TELEFONE, IDADE, SEXO, sendo que CODIGO a chave primria da tabela.
Tabela 1. CLIENTE

CODIGO

CPF NOME

ENDERECO

TELEFONE

IDADE

SEXO

Uma entidade no requer superclasses. Para definir uma entidade, necessrio importar javax.persistence.Entity e javax.persistence.Id . Alm disso deve-se incluir a annotation @Entity antes da definio da classe, e @Id antes do atributo que se deseja ser chave primria. Note que Cliente subclasse de Pessoa. Esta ltima tambm ter em sua

declarao estas duas annotations. 3.3. Manipulando Entidades A conexo entre os objetos entidades e o banco de dados manipulada por um objeto do tipo EntityManager. Um exemplo de cdigo que manipula entidades do tipo Cliente exibido no cdigo 2: package examples.entity.intro; import java.util.List; import javax.ejb.Stateless; import javax.ejb.Remote; import javax.persistence.PersistenceContext; import javax.persistence.EntityManager; import javax.persistence.Query; @Stateless @Remote(Loja.class) public class BeanLoja implements Loja { // o objeto do tipo EntityManager @PersistenceContext private EntityManager manager; public Cliente novoCliente(String nomeCliente, String endCliente, int telCliente) { Cliente cliente = new Cliente(); ... manager.persist(cliente); return cliente; } public int getNomeCliente(int codigoCliente) { Cliente cliente = manager.find(Cliente.class, codigoCliente); return cliente.nome; } }
Cdigo 2. Um bean que manipula a entidade Cliente

A declarao de um objeto do tipo EntityManager deve vir precedida da annotation @PersistenceContext. No Cdigo 2, declaramos um objeto manager com o

tipo EntityManager. Trs operaes com o objeto manager esto exemplificadas. A primeira aplicada ao mtodo novoCliente(), que cria um novo objeto Cliente e o armazena no banco de dados como um novo registro da tabela CLIENTE. Aps criar o objeto, este no tem relao comtex o banco de dados ainda. Para tanto, ele deve ser passado para um dos mtodos do objeto manager. O mtodo manager.persist(cliente) informar que o novo objeto cliente dever ser gravado no banco de dados como um novo registro da tabela CLIENTE. A gravao em si s ocorre quando a funo retorna, isto , quando o contexto da mesma acaba. O mtodo getNomeCliente(codigoCliente) informa o nome do cliente cujo nmero do cdigo igual a codigoCliente (codigo a chave primria). Para tanto, necessrio buscar um registro da tabela CLIENTE no banco de dados cujo nmero do cdigo igual a codigoCliente. O mtodo manager.find(Cliente.class, codigoCliente) faz isso. Ele retorna um objeto do tipo Cliente com todos os atributos preenchidos de acordo com o registro da tabela. Ento o nome pode ser obtido diretamente do objeto. 3.4. Sincronizao com o Banco de Dados Por padro a sincronizao com o banco de dados ocorre automaticamente no momento do commit. Em EJB, o commit no chamado de forma explcita, e normalmente ocorre quando a funo retorna. No entanto possvel sincronizar explicitamente, com o uso dos mtodos flush(), que atualiza o banco de dados de acordo com os objetos instanciados, e refresh(objeto entidade), que atualiza o objeto de acordo com o que est no banco de dados. Os mtodos flush() e refresh() pertencem API de EntityManager.

Figura 1. Figura ilustrativa do uso do mtodo flush()

Figura 2. Figura ilustrativa do uso do mtodo refresh()

3.5. Concorrncia Por padro, se houver conflitos de concorrncia, somente a primeira transao que

tentou modificar o mesmo dado tem permisso para faz-lo, as outras sofrem rollback. Para possibilitar a deteco automtica de conflitos, necessrio marcar um atributo numrico inteiro com a annotation @Version. Este atributo ser incrementado sempre que uma atualizao acontece, o que possibilita a deteco de conflitos. Um exemplo est explicitado abaixo, no Cdigo 3. @Entity public class Cliente { @Version public int verso; //... }
Cdigo 3. Uso de @Version em uma entidade

O EntityManager tambm prov uma forma de bloquear uma entidade, usando o mtodo lock(objeto entidade, LockMode.modo), em que modo pode ser WRITE ou READ. A nica diferena nos dois modos que com WRITE o atributo marcado com @Version incrementado. 3.6. Herana O Java Persistence d suporte ao uso de herana. Existem algumas estratgias para sua utilizao. Essas estratgias do suporte ao conceito de herana da orientao a objeto a banco de dados relacional. Uma nica tabela por hierarquia Uma tabela separada por subclasse Uma nica tabela por entidade Para explicar essas trs estratgias iremos utilizar um modelo de objetos como referncia. Nesse modelo, temos como superclasse Pessoa e as subclasses Cliente e Cliente VIP. Os mtodos setters e getters foram omitidos.

Figura 1. Classes exemplo para herana

A codificao no difere muito da codificao normal de Java. As particularidades da codificao EJB estaro em destaque ao longo do cdigo. 3.6.1. Uma nica tabela por hierarquia Nessa estratgia uma nica tabela utilizada para representar uma hierarquia entre classes. As subclasses so diferenciadas atravs de uma coluna discriminator. Para indicar esta estratgia necessrio adicionar um conjunto de annotations antes da definio da classe entidade. No caso da superclasse Pessoa, adicionamos as annotations especificados a seguir: @Entity @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name=DISC, discriminatorType=DiscriminatorType.STRING) @DiscriminatorValue(Pessoa)
Cdigo 4. Annotations para especificao da estratgia de herana

A annotation @Inheritance indica a estratgia de herana que queremos usar, que nesse caso uma nica tabela por hierarquia. O @DiscriminatorColumn indica o nome da coluna e tipo para discriminar duas subclasses. O @DiscriminatorValue indica o valor que ser persistido na coluna discriminante. Caso as tabelas no tenham sido criadas ainda, sero segundo regras construdas a partir das annotations presentes no cdigo. Para a entidade PessoaSingle teremos a seguinte DDL (Data Definition Language) gerada:
CREATE TABLE PESSOASINGLE ( CPF INTEGER NOT NULL, NOME VARCHAR (31), ENDERECO VARCHAR (31), TELEFONE INTEGER, IDADE INTEGER, SEXO CHAR, DISC VARCHAR(31), CODIGO INTEGER, DATACADASTRO DATE, LIMITECREDITO DOUBLE, NIVEL INTEGER );

Cdigo 5. DDL para a tabela gerada a partir da entidade Pessoa

O cdigo DDL mostra que todos os atributos de todas as classes que participam da hierarquia sero campos da tabela, ou seja, teremos uma nica tabela representando a

hierarquia. Na Tabela 2 temos uma representao de alguns dados persistidos.


Tabela 2. Dados persistidos
CPF COD DISC NOM ENDER TEL IDADE SEXO LIMITCRED DATACAD NIVEL 50 45 M F 1000 2500 05/06/05 07/08/04 NULL 1

00873303504 123 97832145610 456

PESSOA TITO RUA ALBERT 3555-5555 CLIENTE DANI RUA CARLOS 4444-1236

3.6.2. Uma tabela separada por subclasse Nessa estratgia temos uma tabela para cada subclasse na hierarquia. A tabela consiste apenas das propriedades da subclasse corresponente e so definidas separadamente da superclasse. No cdigo ns retiramos o discriminator e alteramos o tipo de herana da superclasse. Vejamos no trecho de cdigo abaixo: @Entity @Table(name = PESSOAJOINED) @Inheritance (strategy=InheritanceType.JOINED) public class Pessoa { ... }
Cdigo 6. Pessoa com uma tabela por subclasse

Dessa vez utilizamos InheritanceType.JOINED para indicar que estamos utilizando uma tabela por subclasse. O atributo CPF (chave primria) da superclasse ser utilizada como chave estrangeira (foreign key) para as tabelas que representam as subclasses na hierarquia. A annotation @Table d um nome diferente do nome da tabela a classe. Por default o container gerar um nome para tabela com base nome da classe. Cada tabela tem uma coluna CPF que ser utilizada com ponto juno (JOIN) quando trabalharmos com as entidades individualmente. A tabela abaixo representa a juno das subclasses que so representadas por tabelas individuais.
Tabela 3. PESSOAJOINED

CPF
00873303504 97832145610

DTYPE
PESSOA CLIENTE

NOME
GUILHERME DANILO

DATACAD
05/06/2005 07/08/2004

NIVEL
NULL 3

3.6.3. Uma tabela por classe entidade concreta Esta estratgia no requerida em EJB 3.0, por isso no ser abordada neste artigo. 3.7. Polimorfismo Em EJB 3.0, o polimorfismo funciona da mesma forma que em Java. O Cdigo 7 mostra um exemplo de uso de um mtodo atualizaEndereco() que espera um objeto do tipo Pessoa em um dos parmetros. Por isso, ele pode receber um objeto do tipo Cliente, que classe-filha de Pessoa. @Stateless public class BeanLoja implements Loja {

@PersistenceContext EntityManager manager; public atualizaEndereco(Pessoa pessoa, String novoEndereco){ pessoa.setEndereco(novoEndereco); } public atualizaClientes() { Pessoa joao = manager.find(Pessoa.class, 45862318795); Cliente jose = manager.find(Cliente.class, 45632897512); atualizaEndereco(joao, Rua H); atualizaEndereco(jose, Rua L); } }
Cdigo 7. Exemplo de uso de polimorfismo.

3.8. Relacionamento As verses 2.x do EJB j traziam suporte a relacionamento. No EJB 3.0 o trabalho foi simplificado de forma significativa. O funcionamento d-se atravs do uso de annotations especficas. So quatro os tipos de relacionamentos: Um-para-um Um-para-muitos Muitos-para-um Muitos-para-muitos O tipo Muitos-para-um anlogo a Um-para-muitos, por isso no ser abordado neste artigo. 3.8.1. Um-para-um No relacionamento um-para-um cada constituinte est relacionado no mximo a um outro constituinte. Esse tipo de relacionamento normalmente determinado por uma foreign key (chave estrangeira) no banco. Vamos supor agora que um cliente s posssa ter um cnjugue, que da classe Pessoa. Neste caso, devemos adicionar os dados na classe Cliente para que ele tenha conhecimento do cnjugue. @Entity public class Cliente extends Pessoa { ...

private Pessoa conjugue; ... @OneToOne(cascade=(CascadeType.PERSIST)) public Pessoa getConjugue(){ return conjugue; } ... }
Cdigo 8. Exemplo de relacionamento Um-para-um

3.8.2. Um-para-muitos No relacionamento um-para-muitos, um dos constituintes est relacionado a um ou mais outros constituintes. Vamos supor que um cliente possa ter mais de um carto de crdito. Abaixo apresentamos as modificaes necessrias para a classe Cliente. A classe entidade Carto necessita ter uma definio comum como entidade. @Entity public class Cliente extends Pessoa { ... private Collection<Cartao> cartoes; ... @OneToMany(cascade=(CascadeType.ALL), fetch=FetchType.EAGER) public Collection<Cartao> getCartoes(){ return cartoes; } ... }
Cdigo 9. Exemplo de relacionamento Um-para-muitos

3.8.3. Muitos-para-muitos No relacionamento muitos-para-muitos, um grupo de constituintes est relacionado a outro grupo de constituintes. Vamos supor que uma pessoa curse vrios cursos e cada curso treine vrias pessoas. @Entity public class Pessoa { ... private Collection<Curso> cursos; ...

@ManyToMany(cascade=(CascadeType.ALL), fetch=FetchType.EAGER) @JoinTable(name=PESSOAS_CURSOS) public Collection<Curso> getCursos(){ return cursos; } ... }


Cdigo 10. Exemplo de relacionamento Muitos-para-muitos classe Pessoa

@Entity public class Curso{ ... private Collection<Pessoa> estudantes; ... @ManyToMany(cascade=(CascadeType.ALL), fetch=FetchType.EAGER) @JoinTable(name=PESSOAS_CURSOS) public Collection<Pessoa> getEstudantes (){ return estudantes; } ... }
Cdigo 11. Exemplo de relacionamento Muitos-para-muitos classe Curso

4. EJB: Query Language EJB-QL


O EJB-QL uma linguagem para consulta de objetos. Muito similar SQL, foi criada com a inteno de tornar transparente o mecanismo de persistncia. A idia foi criar uma linguagem para definir finders CMP - Container-Managed Persistence - (e outros mtodos) que no dependessem de um xml proprietrio do container. Finders que usam EJB-QL so portveis e podem ser usados por qualquer container EJB. O container "traduz" a query EJB-QL para a linguagem a qual o mecanismo de persistncia por ele utilizado entenda, normalmente SQL, ou seja, sua codificao no est amarrada a um tipo especfico de banco de dados. Isso possibilita uma maior portabilidade do cdigo para EJB, pois ele poder ser usado em uma gama maior de bancos de dados, seja ele MySQL, PostgreSQL, ou Microsoft SQL Server. EJB-QL inclui operaes j conhecidas do banco de dados relacional como SELECT, UPDATE, DELETE, JOIN, GROUP BY, entre outros. No Cdigo 12 especificamos dois exemplos simples de uso de EJB-QL, um para consulta simples e outro usando join.

SELECT a FROM Cliente a SELECT c FROM CompanyOMUni c JOIN c.employees e


Cdigo 12. Exemplos de uso de EJB-QL

O uso de queries em JPA se d pelo uso de um objeto do tipo Query. O Cdigo 13 mostra o mtodo listaClientes(), que poderia ser adicionado classe entidade Cliente. public List<Cliente> listaClientes() { Query query = manager.createQuery(SELECT a FROM Cliente a); return query.getResultList(); } }
Cdigo 13. Exemplo de uso de query em JPA

O mtodo listaClientes() retorna uma lista de todos os clientes cadastrados. Manager.createQuery(SELECT a FROM Cliente a) faz a consulta no banco de dados e retorna um objeto do tipo Query. Com query.getResultList(), obtemos a lista com todos os objetos retornados pela query SELECT a FROM Cliente a.

5. Concluso
A nova API Java Persistence permite uma codificao das entidades de forma similar s classes comuns Java (POJO), facilitando o aprendizado por quem j conhece Java, e simplificando o desenvolvimento. O uso de um container EJB facilita ainda mais o desenvolvimento, por j prover vrios servios, inclusive de segurana, concorrncia, e gerenciamento de transaes. tambm fornecida independncia em relao a qual banco de dados relacional utilizada, com o uso de EJB-QL.

Referncia
Rima Patel Sriganesh, Gerald Brose, Micah Silverman (2006) Mastering Enterprise JavaBeans 3.0

Potrebbero piacerti anche