Come per i session bean, anche gli entity hanno una particolare gerarchia da seguire: un'interfaccia remota (e/o locale), una home remota (e/o locale), la classe bean, uno o più descrittori di deployment e (in più rispetto ai session bean) una classe "primary key" che identifichi in maniera univoca le istanze del bean.
L'interfaccia remota deve estendere l'interfaccia javax.ejb.EJBObject
, quella locale jax.ejb.EJBLocalObject
. Le home dovranno estendere javax.ejb.EJBHome
(remota) e javax.EJBLocalHome
(locale). Fin qui nulla di nuovo. Quello che cambia è la classe in cui viene definita la logica, il bean vero e proprio che, negli entity bean deve estendere l'interfaccia javax.ejb.EntityBean
. Vediamo i metodi esportati da questa interfaccia.
Listato 1. Metodi esportati da javax.ejb.EntityBean
package javax.ejb;
import java.rmi.RemoteException;
public interface EntityBean extends EnterpriseBean {
public void setEntityContext(EntityContext ctx) throws EJBException, RemoteException;
public void unsetEntityContext() throws EJBException, RemoteException;
public void ejbRemove() throws RemoveException, EJBException, RemoteException;
public void ejbActivate() throws EJBException, RemoteException;
public void ejbPassivate() throws EJBException, RemoteException;
public void ejbLoad() throws EJBException, RemoteException;
public void ejbStore() throws EJBException, RemoteException;
}
Prima di tutto ricordiamo che i suddetti sono tutti metodi callback
, cioè richiamati dal container in base al ciclo di vita del componente. Dei metodi activate e passivate ne abbiamo discusso nel precedente capitolo: essi servono ad effettuare operazione di swapping. I metodi load e store sono i metodi che più degli altri vengono utilizzati in quanto servono a mantenere sincronizzazione con lo strato di persistenza e a caricare all'interno di un componente i dati di un'istanza, prima di utilizzarla: se la persistenza è su database essi conterranno la logica SQL SELECT (ejbLoad)
e UPDATE (ejbStore)
.
Il metodo remove può essere richiamato quando si decide di eliminare un'istanza dallo strato di persistenza (SQL DELETE
). I metodi set
e unset entity context
, sono invece richiamati dal container al momento della creazione dell'istanza in modo che il componente possa, attraverso la classe Context
, richiamare i servizi dell'application server.
Per quanto riguarda le classi home bisogna fare delle precisazioni: l'operazione di creazione rappresenta la creazione vera e propria di una nuova istanza sullo strato di persistenza. Ciò in virtù del fatto che gli entity bean vengono gestiti con il meccanismo del pooling.
Per recuperare una particolare istanza di bean bisognerà creare dei metodi finder, che si occuperanno di ricercare le istanze (sul database) e restituire le chiavi associate a quelle istanze. I metodi finder si trovano sulle interfacce home (sia remote che locali) ed hanno come tipo di ritorno una classe chiave dell'oggetto (in basso i dettagli sulla classe primary key) oppure una Collection di primary key (se il risultato di ricerca non è univoco).
Ogni interfaccia home deve avere almeno un metodo finder (findByPrimaryKey()
) che definisce la logica per il recupero di un istanza sulla base della primary key passata in riferimento. Ad ogni metodo finder sarà associato sul bean di logica il corrispettivo metodo ejbFind
.
Quindi, quando avremo bisogno di recuperare un'istanza già presente non dovremo utilizzare il metodo create, ma i metodi finder previsti per quel componente. È evidente che se lo strato di persistenza è un database, questi metodi conterranno la logica SELECT SQL
.
L'operazione di creazione (create
) sulla home sarà pertanto un'operazione di logica SQL INSERT
, riferendoci a persistenza su database.
Ritorniamo un passo indietro: abbiamo accennato alla presenza di una classe che definisce la primary key. Tale classe racchiuderà quei valori che sono chiave, cioè che rappresentano in maniera univoca un'istanza rispetto ad un'altra. Si può trattare di classi con un semplice campo numerico (che rappresenta un identificativo) o con più variabili di istanza: importante è che tali classi estendano l'interfaccia Serializable
e definiscano i metodi di uguaglianza (boolean equals()
).
Questo si rende necessario in quanto, per rendere possibile il pooling dei componenti, l'identità (definita dal valore della chiave), rimane esterna al componente stesso e recuperata dinamicamente ad ogni necessità.
Il prossimo capitolo mostra, con un esempio, come creare un entity bean managed persistence (in seguito EBMP) e in seguito vedremo la differenza e i pro e i contro rispetto agli entity container managed persistence che semplificano lo sviluppo dei componenti.