我想为我的 DAO 层应用通用设计模式,这样我就可以轻松地在第三方 ORM(Hibernate、JPA 等)之间切换。显然,我们有一些适用于所有 DAO 的通用方法,例如:
- 公共无效创建(T实体);
- 公共无效更新(T实体);
- 公共无效删除(对象pk);
- 公共T读取(对象pk);
- 公共列表 readAll();
所有 DAO 都必须继承这些方法以及每个 DAO 特定的附加方法,我发现以下设计模式适合我,但我不知道如何使用它才能让所有常用方法和专用方法出现在同一个道参考:
首先,我们将为所有常用方法创建一个接口:
public interface GenericDAOINT<T> {
public void create(T entity);
public void update(T entity);
public void delete(Object pk);
public T read(Object pk);
public List<T> readAll();
}
我们将创建一个实现该接口的抽象类:
public abstract class GenericDAOHibernate<T> implements GenericDAOINT<T> {
private Class<T> persistentClass;
private Session session;
private static SessionFactory sessionFactory;
private static Logger LOGGER = Logger.getLogger("InfoLogging");
public GenericDAOHibernate(T theClass) {
this.persistentClass = (Class<T>) theClass;
session = sessionFactory.openSession();
}
public Class<T> getPersistentClass() {
return persistentClass;
}
public void setPersistentClass(Class<T> persistentClass) {
this.persistentClass = persistentClass;
}
static {
sessionFactory = new Configuration().configure("hibernate.cfg.xml")
.buildSessionFactory();
}
public Session getSession() {
return session;
}
public void create(T entity) {
// implementation
}
public void update(T entity) {}
public void delete(Object pk) {}
public T read(Object pk) {}
public List<T> readAll() {}
}
之后,我们将制作一个 DAOFactory,使我能够在不同的 ORM 之间顺利切换:
public abstract class DAOFactory {
public static DAOFactory getInstance(Class factory) {
try {
return (DAOFactory) factory.newInstance();
} catch (Exception e) {
throw new RuntimeException("Couldn't create DAOFactory: " + factory);
}
}
// return reference to any desired dao in order to call specialized methods
public abstract RegionHome getRegionDAO();
public abstract ServicesHome getServicesDAO();
public abstract StatusHome getStatusDAO();
}
接下来,我们将为 hibernate 或任何其他可插入的 ORM 创建一个 DAOFactory:
public class DAOFactoryHibernate extends DAOFactory {
public GenericDAOHibernate<?> instantiateDAO(Class<?> daoClass)
{
try
{
GenericDAOHibernate<?> dao = (GenericDAOHibernate<?>) daoClass.newInstance(); // Exception is thrown here
return dao;
} catch (Exception e) {
System.out.println(e.toString());
throw new RuntimeException("Can not instantiate DAO: " + daoClass, e);
}
}
@Override
public RegionHome getRegionDAO() {
// TODO Auto-generated method stub
return null;
}
@Override
public ServicesHome getServicesDAO() {
// TODO Auto-generated method stub
return null;
}
@Override
public StatusHome getStatusDAO() {
// TODO Auto-generated method stub
return null;
}
}
为了给每个 DAO 增加专业化,我们将为每个 DAO 创建一个接口,该接口将扩展GenericDAOINT
为包含每个 DAO 中用于 ServicesDAO 的通用方法,我们将执行以下操作:
public interface ServicesDAO<T> extends GenericDAOINT<ServicesHome> {
public void specializedMethod();
}
最后,我们将为特定于 Hibernate 的 ServicesDAO 创建一个具体的类,如下所示:
public class ServicesDAOHibernate extends GenericDAOHibernate implements ServicesDAO {
public ServicesDAOHibernate(Class theClass) {
super(theClass);
// TODO Auto-generated constructor stub
}
@Override
public void specializedMethod() {
System.err.println("Specialized Method");
}
}
我认为这些模式有助于在 ORM 之间轻松灵活地切换过程,但我告诉你的另一面是我想为每个 DAO 在相同的引用上调用所有方法(Common + Specialized),我尝试了以下客户端代码:
public class test {
public static void main(String args[]) {
DAOFactoryHibernate DFH = (DAOFactoryHibernate) DAOFactory.getInstance(DAOFactoryHibernate.class);
ServicesDAOHibernate serviceObjectDAO=(ServicesDAOHibernate) DFH.instantiateDAO(ServicesDAOHibernate.class);
serviceObjectDAO.specializedMethod();
}
但我得到以下异常:
Exception in thread "main" java.lang.RuntimeException: Can not instantiate DAO: class ServicesDAOHibernate
Caused by: java.lang.InstantiationException: ServicesDAOHibernate
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at DAOFactoryHibernate.instantiateDAO(DAOFactoryHibernate.java:9)
我想知道如何像以前的客户端代码一样在同一个引用上调用所有方法(Common + Specialized)。