Entity beans BMP Persistência explícita Ricardo Cavalcanti [email protected] Jobson Ronan...
-
Upload
terezinha-furtado-marinho -
Category
Documents
-
view
221 -
download
0
Transcript of Entity beans BMP Persistência explícita Ricardo Cavalcanti [email protected] Jobson Ronan...
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.