Viele Applikationen sowie Java-EE-Anwendungen werden heute genau an Kundenanforderungen angepasst und so detailliert spezifiziert, dass diese ohne Modifikationen oder Neuentwicklungen nicht für weitere Kunden verwendet werden können. Durch die EJB3-(Enterprise-JavaBeans-)Spezifikation ist das Entwickeln solcher Systemen einfacher geworden. Die JPA (Java Persistence API) ermöglicht den Einsatz von Entity Beans und bringt ein standardisiertes OR Mapping (Object Relational Mapping) mit sich. Des Weiteren wird im Package javax.persistence das EntityManager Interface angeboten, um den Zugriff auf die Entitäten zu ermöglichen. Die Implementierung des EntityManagers wird von einem OR Mapping-Anbieter wie Hibernate oder Toplink bereitgestellt. Üblicherweise wird der EntityManager innerhalb eines EJB Containers mittels der Annotation @PersistenceContext aus dem Package javax.persistence, geladen:
@PersistenceContext(unitName = "PERSISTENCE_UNIT_NAME")private EntityManager entityManager;
Der unitName-Parameter der Annotation muss bereits zur Programmierzeit bekannt sein und lässt somit keinen Spielraum für ein dynamisches Wechseln der dahinter liegenden Datenbanken zu. Es stellt sich die Frage, wie es nun möglich wird, eine solche Dynamik in den Code zu bringen.
Um für den oben genannten generischen DAO Layer eine bestmögliche Anwendung zu gewährleisten, ist es ratsam, ein eigenes Entity-Interface (Marker-Interface) anzubieten (Listing 1). Damit sollten alle Entitäten des Systems das Marker-Interface implementieren. Dieses Interface ermöglicht auch ein einfaches Anbinden an Legacy-Systeme.
Listing 1: Entity-Marker-Interface und konkrete Entity-Klasse// Marker interface.package javamagazin.virtual.entities;import java.io.Serializable;public interface Entity extends Serializable {}// Entity classpackage javamagazin.virtual.entities;@Entitypublic class User implements Entity {....private static final long serialVersionUID = -7931125774297472732L;@Column(nullable = false)private String username;private String firstname;private String lastname;// ... getter and setter Methods}
Der generische DAO Layer teilt sich in ein BaseDao-Interface und eine BaseDaoImpl-Implementierung. Dieses BaseDao-Interface ist ein Wrapper für den EntityManager. Methoden für das Laden von einzelnen und mehreren Entitäten sowie das Speichern, Updaten und Löschen werden von Entitäten angeboten. Wie die Aufteilung in Interface und Implementierung vermuten lässt, wird dieses DAO als EnterpriseBean angeboten. Oft ist es sinnvoll, das BaseDao sowie die dazugehörige Implementierung nicht als EnterpriseBean zu deklarieren, sondern für unterschiedliche Projekte eigene DAO-Interfaces und -Implementierungen, die das BaseDao erweitern, anzubieten (Listing 2), um weitere spezifischere Methoden zur Verwaltung von Interaktion mit Entitäten bereitzustellen.
Listing 2: BaseDao und Erweiterung// BaseDao interfacepackage javamagazin.virtual.dao;public interface BaseDao {<T extends Entity> T get(String key, Class<T> entity, Serializable id);<T extends Entity> T load(String key, Class<T> entity, Serializable id)throws NoSuchEntityException;<T extends Entity> T getByQuery(String key, String namedQuery,Object... parameters);<T extends Entity> T loadByQuery(String key, String namedQuery,Object... parameters) throws NoSuchEntityException;<T extends Entity> List<T> findByQuery(String key, String namedQuery,Object... parameters);<T extends Entity> Serializable save(String key, T entity);<T extends Entity> void update(String key, T entity);<T extends Entity> void delete(String key, T entity);<T extends Entity> Serializable merge(String key, T entity);<T extends Entity> void refresh(String key, T entity);<T extends Entity> void refresh(String key, List<T> entities);}// Concrete local dao interfacepackage javamagazin.virtual.dao;@Localpublic interface VirtualDao extends BaseDao {// Any specific methods for the VirtualDao.}// concrete stateless enterprise beanpackage javamagazin.virtual.dao;@Statelesspublic class VirtualDaoImpl extends BaseDaoImpl implements VirtualDao {// Implementation of all specific VirtualDao methods.}
Wie in Listing 2 zu sehen ist, übernimmt jede Interfacemethode einen Schlüssel (key). Dieser Schlüssel ist ausschlaggebend, um den für den zugreifenden Kunden richtigen EntityManager zu laden. Konfiguriert wird dieser Zugriff in der ejb-jar.xml.









