2013-05-16 32 views
1

我想爲我的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) 

我想知道該怎麼稱呼都像以前的客戶端代碼相同的參考方法(通用+專業)。

+0

JPA已經是各種實現(EclipseLink,Hibernate等)之上的常見抽象層。你爲什麼要添加另一個圖層?是什麼改變了ORM的概率,你爲什麼不等到這個高度不可能事件重構代碼? YAGNI! –

+0

因爲某些原因我現在使用Hibernate,但我想添加它上面的可插拔層爲未來切換到另一個ORM –

+0

當你看到我的DAOFactory增加了一個抽象給我,我可以添加任何ORM具體實現,因爲我與DAOFactoryHibernate做 –

回答

1

我希望你能發佈完整的堆棧跟蹤(你錯過了導致問題的根本原因)。但從看你的代碼,你的問題似乎是你通過Class.newInstance()ServicesDAOHibernate上調用無參數構造函數,並且該類沒有無參數構造函數。你想使用

return (GenericDAOHibernate<?>) daoClass.getConstructor(Class.class) 
    .newInstance(daoClass);