Entity beans BMP Persistência explícita Ricardo Cavalcanti roc3@cin.ufpe.br Jobson Ronan...

Post on 07-Apr-2016

221 views 0 download

Transcript of Entity beans BMP Persistência explícita Ricardo Cavalcanti roc3@cin.ufpe.br Jobson Ronan...

Entity beans BMP

Persistência explícita

Ricardo Cavalcantiroc3@cin.ufpe.br

Jobson Ronanjrjs@cin.ufpe.br

2

Introdução

Entity beans são objetos persistentes Sincronizam seu estado através um

mecanismo de persistência Dois tipos de gerenciamento de

persistência Bean Managed Persistence Container Managed Persistence

3

Persistência

Serialização Facilidade de leitura e gravação Dificuldade de consultas à base

Alternativas Bancos de dados relacionais (JDBC) Bancos de dados Orientados a objeto Mapeamento Objeto relacional

4

O/R Mapping

Decompor os objetos em campos de uma tabela

ISBN Autor Titulo

0471208310 MARINESCU, FLOYD

EJB DESIGN PATTERNS

0321278658 BECK, KENT EXTREME PROGRAMMING EXPLAINED - EMBRACE CHANGE

8575220470 TELES, VINICIUS MANHAES

EXTREME PROGRAMMING

Classe Livro

String ISBNString autorString titulo

instância: Livro

ISBN = 0321278658Autor = “BECK, KENT”Titulo = “EXTREME PROGRAMMING...”

5

Entity bean Session beans modelam tarefas realizadas

pelo sistema Entity beans modelam as entidades

Representam dados Session beans stateful não representam dados! Independente da forma de armazenamento

Dois termos distintos Entity bean instance: os dados na memória

(instância da classe do Entity Bean) Entity bean data: os dados fisicamente

armazenados no banco

6

Mais diferenças entre Session e Entity Entity beans

têm ciclo de vida independente da aplicação cliente

têm identidade e estado visível para o cliente

são concorrentes

7

Componentes do Entity bean

Além de: interface Home ou LocalHome, interface Remote ou Local, deployment descriptor, classe EJB

Mapeamento da classe à uma definição de entidade de um esquema de banco de dados

métodos especiais que lidam com a sincronização do EntityBean com o banco de dados

Um entity bean tem uma classe Primary Key que permite identificar sua instância

8

Primary Key Identifica o entity bean unicamente Uma classe PK deve ser serializável e

têm Pelo menos um construtor público sem

argumentos Atributos públicos que formam a chave Métodos equals e hashcode

String e Wrapper classes podem ser usados

9

Exemplo: Primary Keypublic class AccountPK implements java.io.Serializable {

public String accountID;public AccountPK(String id) {this.accountID = id;}public AccountPK() { }

public String toString() {return accountID;}

public int hashCode() {return accountID.hashCode();}public boolean equals(Object account) {return ((AccountPK) account).accountID.equals(accountID);}

}

10

Características do Entity bean

Tolerante a falhas Podem ser reconstituídos após a queda

do servidor Basta ler os dados novamente!

Ciclo de vida muuuuuito longo Antes mesmo da aplicação pensar em

ser feita já existem Entity beans Dados legados

11

Sincronia A sincronia com a base permite pensar

instance e data com um só. Container controla a sincronia

Todas as classes implementam métodos que realizam essa atualização

void ejbLoad() lê os dados da base para dentro do entity bean

void ejbStore() grava os dados do entity bean na base

12

ejbLoad e ejbStore

Container/Server

Instância de Entity bean

1:ejbLoad()

4:ejbStore()

2:Lê da base 5: grava na base

3: Métodos de negócio

Base de dados

13

Concorrência

Entity beans são concorrentes Múltiplas instâncias podem

representar o mesmo dado Melhorar performance

O Container controla a sincronia através de transações

14

Pooling

Para otimizar recursos Economizar tempo de

criação ejbActivate()

Adquirir recursos ejbPassivate()

Largar recursos

cliente

cliente

Free Pool

15

Pooling e sincronismo Container Instância do

bean

1:ejbStore()

2:ejbPassivate()

1:ejbLoad()

2:ejbActivate()

16

Tipo de persistência Bean-managed persistence (BMP)

UPDATE no ejbStore, SELECT no ejbLoad e INSERT no ejbCreate (com um BD relacional)

Container-managed persistence (CMP) O container gera código para garantir a

sincronia com a base

17

Criando e removendo beans Entity beans são dados, portanto

Criar um bean = inserir dados na base Remover um bean = remover dados

Se você tiver o seguinte ejbCreate() no beanpublic AccountPK ejbCreate(String id, String owner) ...

Você deve ter o seguinte create() na Homepublic Account create(String id, String owner) ...

O bean retorna a chave primária para o container, que acha o dado utilizando-a e entrega ao cliente um objeto que implementa a Component interface .

Para destruir um bean: remove() na Home ou na Component interface

ejbRemove() é o correspondente no bean. Ele destrói o dado, mas preserva o bean para ser reciclado

18

Localizando entity beans Entity Beans podem ser localizados

quando já existirem Todo bean pode ser localizado através de sua

chave primária Métodos find() adicionais podem ser criados

para localizar beans de acordo com outros critérios

Finder methods na home interface No home: EJBObject findXXX(...) No EJB: PK ejbFindXXX(...) Deve existir pelo menos o findByPrimaryKey()

19

Métodos find Todos devem declarar que lançam

FinderException Métodos de retorno simples devem

retornar uma referência de EJBObject ou EJBLocalObject, na interface Home Lançam ObjectNotFoundException, caso não

encontrem o EJB Métodos com retorno múltiplo devem

retornar uma Collection de chaves primárias Retornam a Collection vazia caso não encontre

nada

20

Modificando sem EJB

Você pode mudar diretamente na base As mudanças serão refletidas no Entity

bean, porém... Problemas de cache podem ocorrer:

evite!

21

Entity Context Estende EJBContext Através dele pode-se

Obter o EJBObject ou o EJBLocalObject associado Obter a chave primária

getPrimaryKey() é essencial em ejbLoad() e ejbRemove() para descobrir qual a instância que será carregada ou removida, respectivamente

EjbContextEjbContext

BeaninRole?

Principal

EJBHomeEJBHome

EJBLocalHome

EJBLocalHome

handlers

transaçõesPK

EJBObject

EJBLocalObject

EntityContext

22

Classe do bean Métodos da interface Home

Para cada create() da Home, um par ejbCreate/postCreate com a mesma assinatura

Para cada find da remote um ejbFind correspondente Para cada “home method” xxx() um ejbHomeXxx

Métodos da Component interface Todos os criados por você

Métodos da interface EntityBean ejbActivate e ejbPassivate ejbLoad e ejbStore ejbRemove setEntityContext e unsetEntityContext

23

Métodos da interface Home PK ejbCreate

Atua como construtor do bean, inserindo na base de dados Tipo de retorno deve ser a PK

void ejbPostCreate Chamado pelo container após o ejbCreate Pode ser utilizado para passar referências de outros beans para o seu

bean Pode ser vazio

ejbFindXXX Localiza os beans Retorna

• a Component interface ou • Collection, para retornar múltiplos beans

Pode haver vários, apenas o ejbFindByPrimaryKey é obrigatório ejbHomexxx

Um método da interface home

24

Métodos da interface EntityBean

ejbLoad Deve conter query SELECT ou equivalente e em seguida

atualizar os atributos do bean com os dados recuperados

Use context.getPrimaryKey() para saber qual a chave primária do bean a ser lido

ejbStore Deve conter query UPDATE ou equivalente e gravar no

banco o estado atual dos atributos do objeto ejbRemove

Chamado antes que os dados sejam removidos do banco Deve conter query DELETE ou equivalente Use context.getPrimaryKey() para saber qual a chave

primária do bean a ser removido

25

Métodos da interface EntityBean

ejbPassivate Chamado antes da passivação do bean

ejbActivate Chamado logo após a ativação do bean

setEntityContext Chamado após a criação da instância no pool. O contexto passado deve ser gravado em variável de

instância pois pode ser usado para obter a chave primária da instância atual

unsetEntityContext Destrói a instância (será recolhida pelo GC). Isto destrói

o objeto, mas não o entity bean (os dados)

26

Exemplo: Interface do Componentepublic interface Account extends EJBObject {

public void deposit(double amt)throws AccountException, RemoteException;

public void withdraw(double amt)throws AccountException, RemoteException;

public double getBalance()throws RemoteException;

public String getOwnerName()throws RemoteException;

public void setOwnerName(String name)throws RemoteException;

public String getAccountID()throws RemoteException;

public void setAccountID(String id)throws RemoteException;

}

27

Exemplo: Interface Homepublic interface AccountHome extends EJBHome {

Account create(String accountID, String ownerName)throws CreateException, RemoteException;

public Account findByPrimaryKey(AccountPK key)throws FinderException, RemoteException;

public Collection findByOwnerName(String name)throws FinderException, RemoteException;

public double getTotalBankValue()throws AccountException, RemoteException;

}

28

Exemplo: Classe do Beanpublic class AccountBean implements EntityBean {

protected EntityContext ctx;private String accountID; // PKprivate String ownerName;private double balance;// Getters e Setterspublic String getAccountID() {...} ...// Métodos de negóciopublic void deposit(double amount) {...} ...// Métodos do ciclo de vidapublic void ejbActivate() {...} ...// Métodos de Homepublic AccountPK findByPrimaryKey(AccountPK pk) {}// Métodos de persistênciapublic void ejbLoad() {...} ...

}

29

Exemplo: Acesso via DataSourceprivate Connection getConnection() throws Exception {try {Context ctx = new InitialContext();javax.sql.DataSource ds =(javax.sql.DataSource)ctx.lookup("java:comp/env/jdbc/ejbPool");return ds.getConnection();} catch (Exception e) {System.err.println("Could not locate datasource:");e.printStackTrace();throw e;

}}

30

Exemplo: Ciclo de vidapublic void setEntityContext(EntityContext ctx) {System.out.println("setEntityContext called");this.ctx = ctx;}public void unsetEntityContext() {System.out.println("unsetEntityContext called");this.ctx = null;}public void ejbPassivate() {System.out.println("ejbPassivate () called.");}public void ejbActivate() {System.out.println("ejbActivate() called.");}

31

Exenplo: Métodos de negóciopublic void deposit(double amt) throws AccountException {

balance += amt;}public void withdraw(double amt) throws AccountException {

if (amt > balance) {throw new AccountException("Cannot withdraw "+amt+"!");}balance -= amt;

}// Getter/setter methods on Entity Bean fieldspublic double getBalance() {

return balance;}

public void setOwnerName(String name) {ownerName = name;

}public String getOwnerName() {return ownerName;

}

32

Exemplo: ejbFindByPrimaryKeypublic AccountPK ejbFindByPrimaryKey(AccountPK key)

throws FinderException {PreparedStatement pstmt = null;Connection conn = null;try {

conn = getConnection();pstmt = conn.prepareStatement ("select id from accounts where id = ?");pstmt.setString(1, key.toString());ResultSet rs = pstmt.executeQuery();rs.next();return key;

} catch (Exception e) {throw new FinderException(e.toString());

} finally { con.close(); ... }}

33

Exemplo: ejbCreatepublic AccountPK ejbCreate(String accountID, String ownerName)

throws CreateException {PreparedStatement pstmt = null;Connection conn = null;try {

this.accountID = accountID;this.ownerName = ownerName;this.balance = 0;conn = getConnection();pstmt = conn.prepareStatement("insert into accounts "+"(id, ownerName, balance) values (?, ?, ?)");pstmt.setString(1, accountID);pstmt.setString(2, ownerName);pstmt.setDouble(3, balance);pstmt.executeUpdate();return new AccountPK(accountID);

} catch (Exception e) {throw new CreateException(e.toString());} finally { con.close(); ... }

}public void ejbPostCreate(String accountID, String ownerName) {}

34

Exemplo: ejbFindByOwnerNamepublic Collection ejbFindByOwnerName(String name)

throws FinderException {PreparedStatement pstmt = null;Connection conn = null;Vector v = new Vector();try {

conn = getConnection();pstmt = conn.prepareStatement("select id from accounts where ownerName = ?");pstmt.setString(1, name);ResultSet rs = pstmt.executeQuery();while (rs.next()) {

String id = rs.getString("id");v.addElement(new AccountPK(id));

}

return v;} catch (Exception e) {

throw new FinderException(e.toString());} finally { con.close(); ... }

}

35

Exemplo: ejbHomeGetTotalBankValuepublic double ejbHomeGetTotalBankValue() throws AccountException{

PreparedStatement pstmt = null;Connection conn = null;try {

conn = getConnection();pstmt = conn.prepareStatement("select sum(balance) as total from accounts");ResultSet rs = pstmt.executeQuery();if (rs.next()) {

return rs.getDouble("total");}

} catch (Exception e) {e.printStackTrace();throw new AccountException(e);} finally {...}throw new AccountException("Error!");

}

36

Exemplo: ejbRemovepublic void ejbRemove() throws RemoveException

AccountPK pk = (AccountPK) ctx.getPrimaryKey();String id = pk.accountID;PreparedStatement pstmt = null;Connection conn = null;try {

conn = getConnection();pstmt = conn.prepareStatement("delete from accounts where id = ?");pstmt.setString(1, id);if (pstmt.executeUpdate() == 0) {

throw new RemoveException("...");}

} catch (Exception ex) {throw new EJBException("...", ex);

} finally {...conn.close() ... }}

37

Exemplo: ejbStorepublic void ejbStore() {

PreparedStatement pstmt = null;Connection conn = null;try {

conn = getConnection();pstmt = conn.prepareStatement("update accounts set ownerName = ?,balance = ? where id = ?");pstmt.setString(1, ownerName);pstmt.setDouble(2, balance);pstmt.setString(3, accountID);pstmt.executeUpdate();

} catch (Exception ex) {throw new EJBException("...", ex);

} finally {...conn.close() ... }}

Sempre lance EJBExceptionquando algo sair errado emejbStore() e ejbLoad()

38

Exemplo: ejbLoadpublic void ejbLoad() {

AccountPK pk = (AccountPK) ctx.getPrimaryKey();accountID = pk.accountID;PreparedStatement pstmt = null;Connection conn = null;try {

conn = getConnection();pstmt = conn.prepareStatement("select ownerName, balance from accounts where id = ?");pstmt.setString(1, accountID );ResultSet rs = pstmt.executeQuery();rs.next();ownerName = rs.getString("ownerName");balance = rs.getDouble("balance");

} catch (Exception ex) {throw new EJBException("...", ex);

} finally {...conn.close() ... }}

39

Exemplo: ejb-jar.xml<ejb-jar>

<enterprise-beans><entity>

<ejb-name>Account</ejb-name><home>examples.AccountHome</home><remote>examples.Account</remote><local-home>examples.AccountLocalHome</local-home><local>examples.AccountLocal</local><ejb-class>examples.AccountBean</ejb-class><persistence-type>Bean</persistence-type><prim-key-class>examples.AccountPK</prim-key-class><reentrant>False</reentrant><resource-ref>

<res-ref-name>jdbc/ejbPool</res-ref-name><res-type>javax.sql.DataSource</res-type><res-auth>Container</res-auth>

</resource-ref></entity>

</enterprise-beans><assembly-descriptor>

<container-transaction><method>

<ejb-name>Account</ejb-name><method-name>*</method-name>

</method><trans-attribute>Required</trans-attribute>

</container-transaction></assembly-descriptor>

</ejb-jar>

40

Exemplo: jboss.xml

<jboss><enterprise-beans>

<entity><ejb-name>Account</ejb-name><jndi-name>account/AccountHome</jndi-name>

</entity></enterprise-beans><resource-managers>

<resource-manager><res-name>jdbc/ejbPool</res-name><res-jndi-name>java:/DefaultDS</res-jndi-name>

</resource-manager></resource-managers>

</jboss>

41

Patterns e Entity beans

DAO Abstrai e encapsula o acesso a fontes de

dados Transfer Object

Antes chamado de Value Object Encapsula dados de negócio

42

DAO – Data Access Object

Contexto acesso a dados persistentes.

Problema acoplamento entre lógica de negócios e

lógica de acesso a dados Código SQL junto do código de negócios

43

DAO – Data access object// all imports required// exceptions not handled in the sample code

public class UserAccountEJB implements EntityBean {

    // All EJB methods like ejbCreate, ejbRemove go here

    // Business methods start here

    public UserDetails getUserDetails(String userId) {

        // A simple query for this example        String query = "SELECT id, name, phone FROM userdetails WHERE name = " + userId;

        InitialContext ic = new InitialContext();        datasource = (DataSource)ic.lookup("java:comp/env/jdbc/DataSource");        Connection dbConnection = datasource.getConnection();        Statement stmt = dbConnection.createStatement();        ResultSet result = stmt.executeQuery(queryStr);

        // other processing like creation of UserDetails object

        result.close();        stmt.close();        dbConnection.close();        return(details);    }}

44

DAO – Data access object Forças

Componentes necessitam obter dados de uma fonte persistente

A portabilidade dos componentes é afetada quando um mecanismo específico de persistência é incluído nele

Os componentes devem ser transparentes quanto à persistência para prover uma migração simples para outro tipo de armazenamento

45

DAO – Data access object Solução

Data access object para abstrair e encapsular todo o acesso a dados.

O DAO gerencia a conexão com a fonte de dados além de armazenar e obter os dados

Fonte:Core J2EE Patterns

46

DAO – Data access object

Fonte:Core J2EE Patterns

47

DAO – Data Access object

Pode ser associado com AbstractFactory DAOFactory

Conceqüências Transparêcnia Migração simples Reduz complexidade dos objetos de negócio Centraliza acesso a dados numa nova camada Não é interessante com CMP Cria uma nova camada Quando usado com AbstractFactoru exige mais design

• Pode-se evoluir de um factory method para uma abstract factory

48

Transfer Object Contexto

Clientes necessitam trocar dados com enterprise beans

Problema Muitas chamadas de métodos remotos para

conseguir todos os atributos Forças

Quantidade de chamadas remotas pode ter impacto na performance da rede

Geralmente o cliente necessita de mais de um atributo

Em geral, o cliente lê mais do que altera os dados

49

Transfer Object Solução

Use um Transfer Object para encapsular os dados de negócio.

Apenas um método para obter todo o objeto. O bean preenche o objeto com os atributos e envia

Fonte:Core J2EE Patterns

50

Transfer Object

Fonte:Core J2EE Patterns

51

Transfer Object Conseqüências

Reduz o tráfico da rede Simplifica o objeto remoto e a component

interface Transfere mais dados em menos chamadas Reduz duplicação de código Cópia do cliente pode ficar desatualizada Aumenta complexidade de sincronização

• Objeto alterado enviado de volta ao servidor

52

Quando usar BMP Quando você precisa de controle sobre o

esquema, ou precisa trabalhar com uma base legado específico.

Quando a aplicação necessita de “sintonia fina” Quando portabilidade não é um problema. Mesmo

nesse caso, recomenda-se utilizar DAOs. DAOs facilitam uma futura adaptação do bean para um

novo esquema Quando sua consulta excede a capacidade da

EJB-EL Quando sua base de dados não é suportada pelo

CMP.