Kundendatenbanken mit EJB 3 virtualisieren

Nun sind alle Konfiguration und Informationen zusammengetragen, um schließlich die Implementierung des BaseDaoImpl unter die Lupe zu nehmen. Die Klasse selbst bildet einen Wrapper für den EntityManager und hat gleichzeitig die Aufgabe, dass zur Laufzeit anhand des mitgegebenen Schlüssels entschieden wird, auf welche Datenbank zugegriffen werden muss.

Listing 5: BaseDaoImpl-Implementierung
package javamagazin.virtual.dao
public class BaseDaoImpl implements BaseDao { 
    private static final Logger logger = Logger.getLogger(BaseDaoImpl.class); 
    private static Properties props;
    static {
        if(props == null) {
            synchronized {
                if(props == null)
                    props = new VirtualConfig();
                    try {
                        props.load(VirtualConfig.class.getResourceAsStream(
                            "/virtualConfig.properties"));
                    } catch(Exception e) {
                        logger.error(e.getMessage(), e);
                    }
                }
            }
        }
    }
    private EntityManager lookup(String lookupName) throws NamingException {
        Context ctx = new InitialContext();
        return (EntityManager) ctx.lookup(lookupName);
    }
    protected EntityManager getEntityManager(String key) { 
        logger.debug("Getting an EntityManager for the client: " + key);
        String lookupName = props.get(key); 
        if(lookupName == null) {
            logger.error("No EntityManager for the client: " + key);
            throw new EntityManagerLoadingException(
                "No EntityManager for the client: " + key);
        }
        try {
            return lookup(key);
        } catch (NamingException e) {
            logger.error("No EntityManager for the client: " + key);
            throw new EntityManagerLoadingException(
                "No EntityManager for the client: " + key +
                " and lookup name: " + lookupName);
        }
    }
    protected Query addParametersToQuery(Query query, Object... parameters) { 
        int i = 1; 
        for (Object parameter : parameters) { 
            logger.debug("Adding parameter: " + parameter + 
                " to the query on position: " + i); 
           query.setParameter(i++, parameter); 
        }
       return query; 
    } 
    @Override 
    @SuppressWarnings("unchecked") 
    public  List findByQuery(String key,
        String namedQuery, Object... parameters) { 
        EntityManager entityManager = getEntityManager(key); 
        Query q = addParametersToQuery(entityManager.createNamedQuery(
            namedQuery),parameters); 
        return (List)q.getResultList(); 
    } 
    @Override 
    public  T get(String key, Class entity,
        Serializable id) { 
        EntityManager entityManager = getEntityManager(key); 
       return entityManager.find(entity, id); 
    } 
    @Override 
    @SuppressWarnings("unchecked") 
    public  T getByQuery(String key,
        String namedQuery, Object... parameters) { 
        EntityManager entityManager = getEntityManager(key); 
        Query q = addParametersToQuery(
            entityManager.createNamedQuery(namedQuery), parameters); 
        try { 
            return (T)q.getSingleResult(); 
        } catch (Exception e) { 
            logger.warn("Could not load an entity for the query: " + namedQuery); 
            return null; 
        } 
    } 
    @Override 
    public  Serializable save(String key, T entity) { 
        EntityManager entityManager = getEntityManager(key); 
        entityManager.persist(entity); 
        entityManager.flush(); 
       if (entity instanceof BaseEntity) { 
            return ((BaseEntity)entity).getId(); 
        } 
        return null; 
    } 
    // other BaseDao methods to be implemented ...

Die eigentliche Arbeit, um die richtige Datenbank auszuwählen, übernimmt folgende Methode:

protected EntityManager getEntityManager(String key) { ... }

Diese Methode lädt zu Beginn eine Properties-Datei in ein statisches Properties-Objekt, die die Zuweisung von Kunden und EntityManager-JNDI-Namen beinhaltet. Der Aufbau dieser Methode ist eigentlich recht einfach, da mithilfe des Context-Interfaces ein übliches Laden eines Objektes aus dem JNDI-Baum stattfindet. Da die DAO EnterpriseBean als lokale Bean angeboten wird und dies innerhalb eines Applikationscontainers läuft, müssen dem InitialContext keine Informationen zum Laden der Beans bekanntgegeben werden. Per default wird automatisch auf den lokalen Applikationsserver, aus Sicht der EnterpriseBean, zugegriffen. Weitere Aufmerksamkeit gilt der Methode:

protected Query addParametersToQuery(Query query, Object... parameters) { ... }

Um ebenfalls EJB QLs (Enterprise JavaBeans Query Language) ausführen zu können und vor allem die unterschiedlichen Parameter sowie die unterschiedliche Anzahl der Parameter zu verarbeiten, wurde die oben genannte Methode implementiert. Die Query, die als Parameter übernommen wird, wird als NamedQuery innerhalb der Entität definiert (Listing 6). Der im @NamedQuery definierte eindeutige Name wird dann beim Aufruf der unterschiedlichen DAO Methoden als Parameter übergeben. Der letzte Parameter, den die Methode übernimmt, ist ein Array an Objekten, die genau in der übergebenen Reihenfolge an die Query-Platzhalter, gekennzeichnet mit ?1, ?2 etc. gesetzt werden. Sind keine Platzhalter definiert, muss ein leeres Object[0] übergeben werden.

Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.