Hallo,
Da ich meine Anwendungen immer so entwerfe, dass die einzelnen Schichten immer möglichst lose gekoppelt sind und man so einfach weitere Schichten austauschen / parallel hinzufügen kann (Statt web Präsentationsschicht, ein Eclipse Rich Client) achte ich immer darauf das die einzelnen Schichten möglichst keine zyklischen Abhängigkeiten zueinander haben.
Ich würde das dann so machen:
Präsentationsschicht (JSF, JSP; Servlets) de.tutorials.core.presentation... (hier Model View Controller, oder ein anderes Pattern für den Presentation Layer (MVP, PM))
Geschäftslogikschicht (BusinessServices, Domain Classes) -> de.tutorials.core.services, de.tutorials.core.domain
Persistenzschicht (Legacy System ResourceConnectors,DAO's / Repositories, DataAssembler (JDBC/Spring JDBC basiert zur Massendatenverarbeitung) ) -> de.tutorials.core.persistence, de.tutorials.core.persistence.dao
(de.tutorials.core ist in meinem Beispiel das Basis package des OSGi Bundles)
Für alle BusinessServices,DAO / Repositories 's, DataAssembler, Connectors gibts öffentliche interfaces. Diese liegen im direkten package:
Bsp:
de.tutorials.core.persistence.dao.IGenericDAO
Implementierungen verstecke ich immer in einem darunterliegenden Internal package:
Bsp:
de.tutorials.core.persistence.dao.internal.GenericHibernateDAO
So habe ich die möglichkeit den Klassenzugriff innerhalb der einzelnen Schichten besser zu steuern (per AspectJ, OSGi Exported / Imported Packages, Dynamic Import, etc.).
Geschäftslogik hätte ich in meinen Services und / oder in meinen Domain Classes. Die mapping Informationen (hbm.xml) würde
ich auch in dem Domain package ablegen. Konfigurieren würde ich meine Services / Domain Objects über Spring, mit AspectJ und
@Configurable (
http://www.tutorials.de/forum/java/...-eclipse-rcp-view-mit-aspectj-und-spring.html)
Ansonsten verwende ich für große Webanwendungen eine "Serverside Eclipse" Komponentenmodell. Komponenten sind in diesem Sinne
dann meine OSGi Bundles, die dann Services, Hibernate Mappings, Spring application contexts über extension points und extensions in das Gesamtsystem einbringen. Damit hat man dann einen hochflexiblen Erweiterungsmechanismus
Wenn man dann noch die "Erweiterbarkeit" als AspectJ aspect definiert bleibt die Anwendungslogik auf komplett frei von irgendwelchen Plugin-Mechanismus-Interna... ;-)
Siehe auch:
http://www.tutorials.de/forum/java/...ate-equinox-osgi-eclipse-extensionpoints.html
http://www.tutorials.de/forum/java/...-von-osgi-services-auf-basis-von-equinox.html
http://www.tutorials.de/forum/java/265296-extension-points-eclipse-fleh.html
Weiterhin würde ich nicht notwendigerweise für jedes Domain Object ein eigenes DAO schreiben sondern ein generisches, von dem
ich dann in Spezialfällen ableite.
Beispiel:
Java:
/**
*
*/
package de.tutorials.framework.persistence.dao;
import java.io.Serializable;
import java.util.List;
/**
* @author Thomas.Darimont
*
*/
public interface IGenericDAO {
/**
*
* @param entity
* @return
*/
<TKey extends Serializable> TKey makePersistent(Object entity);
/**
*
* @param entity
*/
void makeTransient(Object entity);
/**
*
* @param key
* @return
*/
<TEntity, TKey extends Serializable> TEntity getBy(Class<TEntity> entityClass, TKey key);
/**
*
* @return
*/
<TEntity> List<TEntity> findAll(Class<TEntity> entityClass);
/**
*
* @param attributeName
* @param attributeValue
* @return
*/
<TEntity> List<TEntity> findByAttribute(Class<TEntity> entityClass,
String attributeName, Object attributeValue);
/**
*
* @param attributeNames
* @param attributeValues
* @return
*/
<TEntity> List<TEntity> findByAttributes(Class<TEntity> entityClass,
String[] attributeNames, Object[] attributeValues);
}
Implementierung:
Java:
/**
*
*/
package de.tutorials.framework.persistence.dao.internal;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Property;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import de.tutorials.framework.persistence.dao.IGenericDAO;
/**
* @author Thomas.Darimont
*
*/
public class GenericHibernateDAO extends HibernateDaoSupport implements
IGenericDAO {
@SuppressWarnings("unchecked")
public <TEntity> List<TEntity> findAll(final Class<TEntity> entityClass) {
return getHibernateTemplate().loadAll(entityClass);
}
@SuppressWarnings("unchecked")
public <TEntity> List<TEntity> findByAttribute(
final Class<TEntity> entityClass, final String attributeName,
final Object attributeValue) {
return getHibernateTemplate().executeFind(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
return session.createCriteria(entityClass).add(
Property.forName(attributeName).eq(attributeValue))
.list();
}
});
}
@SuppressWarnings("unchecked")
public <TEntity> List<TEntity> findByAttributes(
final Class<TEntity> entityClass, final String[] attributeNames,
final Object[] attributeValues) {
return getHibernateTemplate().executeFind(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Criteria criteria = session.createCriteria(entityClass);
for (int i = 0; i < attributeNames.length; i++) {
criteria.add(Property.forName(attributeNames[i]).eq(
attributeValues[i]));
}
return criteria.list();
}
});
}
@SuppressWarnings("unchecked")
public <TEntity, TKey extends Serializable> TEntity getBy(
Class<TEntity> entityClass, TKey key) {
return (TEntity) getHibernateTemplate().get(entityClass, key);
}
@SuppressWarnings("unchecked")
public <TKey extends Serializable> TKey makePersistent(Object entity) {
return (TKey) getHibernateTemplate().merge(entity);
}
public void makeTransient(Object entity) {
getHibernateTemplate().delete(entity);
}
}
verwendet wird das dann beispielsweise so:
Java:
IGenericDAO genericDao = new GenericHibernateDAO(); // normally injected via Spring...
List<Bubu> bubus = genericDao.findAll(Bubu.class);
List<Gaga> gagas = genericDao.findAll(Gaga.class);
List<Bubu> bubus0 = genericDao.findByAttribute(Bubu.class, "aaa", 4711);
List<Bubu> bubus1 = genericDao.findByAttributes(Bubu.class,
new String[] { "aaa", "bbb" }, new Object[] { 4711, 3421 });
Long id = genericDao.makePersistent(new Bubu());
Bubu bubu = genericDao.getBy(Bubu.class, 1L);
Ansonsten nutze ich bei sowas exzessiv die Möglichkeiten des Zusammenspiels von Technologien wie Spring, AspectJ, Hibernate, iBatis,
Terracotta, OSGi, Equinox etc.
Gruß Tom