Entity beans BMP
Persistência explícita
Ricardo Cavalcanti
[email protected]
Jobson Ronan
[email protected]
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

2
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

3
O/R Mapping

Decompor os objetos em campos de uma
tabela
Classe Livro
String ISBN
String autor
String titulo
ISBN
Autor
Titulo
0471208310
MARINESCU, FLOYD
EJB DESIGN PATTERNS
0321278658
BECK, KENT
EXTREME PROGRAMMING
EXPLAINED - EMBRACE
CHANGE
8575220470
TELES, VINICIUS
MANHAES
EXTREME PROGRAMMING
instância: Livro
ISBN = 0321278658
Autor = “BECK, KENT”
Titulo = “EXTREME
PROGRAMMING...”
4
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
5
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

6
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
7
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
8
Exemplo: Primary Key
public 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);
}
}
9
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

10
Sincronia


A sincronia com a base permite pensar
instance e data com um só.
Container controla a sincronia


void ejbLoad()


Todas as classes implementam métodos que
realizam essa atualização
lê os dados da base para dentro do entity bean
void ejbStore()

grava os dados do entity bean na base
11
ejbLoad e ejbStore
Container/Server
1:ejbLoad()
4:ejbStore()
Instância de
Entity bean
2:Lê da base
3: Métodos
de negócio
5: grava na base
Base de dados
12
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
13
Pooling
Para otimizar recursos
 Economizar tempo de
cliente
criação
 ejbActivate()



Free Pool
Adquirir recursos
ejbPassivate()

Largar recursos
cliente
14
Pooling e sincronismo
Container
Instância do
bean
1:ejbStore()
2:ejbPassivate()
1:ejbLoad()
2:ejbActivate()
15
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
16
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 bean
public AccountPK ejbCreate(String id, String owner) ...

Você deve ter o seguinte create() na Home
public 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
17
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()
18
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
19
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!

20
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
EntityContext
EJBLocal
Object
EJBObjec
t
PK
21
Classe do bean

Métodos da interface Home




Métodos da Component interface


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
Todos os criados por você
Métodos da interface EntityBean




ejbActivate e ejbPassivate
ejbLoad e ejbStore
ejbRemove
setEntityContext e unsetEntityContext
22
Métodos da interface Home

PK ejbCreate



void ejbPostCreate




Atua como construtor do bean, inserindo na base de dados
Tipo de retorno deve ser a PK
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
23
Métodos da interface EntityBean

ejbLoad



ejbStore


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
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
24
Métodos da interface EntityBean

ejbPassivate


ejbActivate


Chamado logo após a ativação do bean
setEntityContext



Chamado antes da passivação do bean
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)
25
Exemplo: Interface do
Componente
public 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;
}
26
Exemplo: Interface Home
public 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;
}
27
Exemplo: Classe do Bean
public class AccountBean implements EntityBean {
protected EntityContext ctx;
private String accountID; // PK
private String ownerName;
private double balance;
// Getters e Setters
public String getAccountID() {...} ...
// Métodos de negócio
public void deposit(double amount) {...} ...
// Métodos do ciclo de vida
public void ejbActivate() {...} ...
// Métodos de Home
public AccountPK findByPrimaryKey(AccountPK pk) {}
// Métodos de persistência
public void ejbLoad() {...} ...
}
28
Exemplo: Acesso via
DataSource
private 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;
}
}
29
Exemplo: Ciclo de vida
public 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.");
}
30
Exenplo: Métodos de
negócio
public 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 fields
public double getBalance() {
return balance;
}
public void setOwnerName(String name) {
ownerName = name;
}
public String getOwnerName() {
return ownerName;
31
}
Exemplo:
ejbFindByPrimaryKey
public 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(); ... }
}
32
Exemplo:
ejbCreate
public 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) { 33
}
Exemplo:
ejbFindByOwnerName
public 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(); ... }
}
34
Exemplo:
ejbHomeGetTotalBankValue
public 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!");
}
35
Exemplo:
ejbRemove
public 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() ... }
}
36
Exemplo:
ejbStore
public 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) {
Sempre lance EJBException
throw new EJBException("...", ex);
quando algo sair errado em
ejbStore() e ejbLoad()
} finally {...conn.close() ... }
}
37
Exemplo:
ejbLoad
public 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() ... }
}
38
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>
39
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>
40
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

41
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

42
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);
}
}
43
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

44
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
45
DAO – Data access object
46
Fonte:Core J2EE Patterns
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
47
Transfer Object

Contexto


Problema


Clientes necessitam trocar dados com
enterprise beans
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 altera48os
dados
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
49
Transfer Object
50
Fonte:Core J2EE Patterns
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
51
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.
52
Download

j2ee_pcc_05_BMP