我想爲我的DAO層應用通用設計模式,以便我可以輕鬆地在第三方ORM之間切換(Hibernate,JPA等)。顯然我們有一些所有DAO的常用方法,例如:如何使用GenericDAO的工廠設計模式?
- public void create(T entity);
- public void update(T entity);
- public void delete(Object pk);
- public T read(Object pk);
- public List readAll();
所有的DAO都繼承特定於每個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();
}
下一步,我們將做一個DAOFactory爲休眠或任何其他可插入ORM:
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();
}
,最後我們會爲ServicesDAO特定的具體類對Hibernate如下:
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)
我想知道該怎麼稱呼都像以前的客戶端代碼相同的參考方法(通用+專業)。
JPA已經是各種實現(EclipseLink,Hibernate等)之上的常見抽象層。你爲什麼要添加另一個圖層?是什麼改變了ORM的概率,你爲什麼不等到這個高度不可能事件重構代碼? YAGNI! –
因爲某些原因我現在使用Hibernate,但我想添加它上面的可插拔層爲未來切換到另一個ORM –
當你看到我的DAOFactory增加了一個抽象給我,我可以添加任何ORM具體實現,因爲我與DAOFactoryHibernate做 –