当前位置: 首页 > 知识库问答 >
问题:

如何使用GenericDAO的工厂设计模式?

荣波
2023-03-14

我想为我的DAO层应用一个通用的设计模式,这样我就可以轻松地在第三方ORM(Hibernate、JPA等)之间切换。显然,我们有一些适用于所有DAO的通用方法,比如:

  • 公共无效创建(T实体)
  • 公共无效更新(T实体)
  • 公共作废删除(对象主键)
  • 公共T读取(对象pk)
  • 公共列表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();
}

接下来,我们将为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中包含服务的常用方法。我们将执行以下操作:

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调用同一引用上的所有方法(通用专用),我尝试了以下客户端代码:

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)

我想知道如何像前面的客户机代码一样,在同一个引用上调用所有方法(通用专用)。

共有1个答案

宿淳
2023-03-14

我希望您已经发布了完整的堆栈跟踪(您缺少了一个导致问题的根本原因)。但是从你的代码来看,你的问题似乎是你在通过调用ServicesDAOHibernate上的无参数构造函数。newInstance()并且该类没有无参数构造函数。你想用

return (GenericDAOHibernate<?>) daoClass.getConstructor(Class.class)
  .newInstance(daoClass);
 类似资料:
  • 我正在努力学习创造性设计模式,我想我现在理解了工厂方法模式。但在转向抽象工厂模式时,我找不到它的用途。我知道我错过了一些东西,但不知道在哪里。 在抽象工厂模式中,我们将有一个抽象工厂,混凝土工厂将返回实例。假设我们正在处理汽车的创建。我们将有一个像这样的抽象工厂 我们的混凝土工厂将是 在用户类中,我们将像 我认为我们也可以使用工厂模式构建相同的功能 在用户类中,我们可以 如果我的理解是正确的(如果

  • 介绍 与创建型模式类似,工厂模式创建对象(视为工厂里的产品)时无需指定创建对象的具体类。 工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类。该模式使一个类的实例化延迟到了子类。而子类可以重写接口方法以便创建的时候指定自己的对象类型。 这个模式十分有用,尤其是创建对象的流程赋值的时候,比如依赖于很多设置文件等。并且,你会经常在程序里看到工厂方法,用于让子类类定义需要创建的对象类型

  • 简单工厂(Simple Factory) Intent 在创建一个对象时不向客户暴露内部细节,并提供一个创建对象的通用接口。 Class Diagram 简单工厂把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化。 这样做能把客户类和具体子类的实现解耦,客户类不再需要知道有哪些子类以及应当实例化哪个子类。客户类往往有多个,如果不使用简单工厂,那么所

  • 4. 抽象工厂(Abstract Factory) Intent 提供一个接口,用于创建 相关的对象家族 。 Class Diagram 抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂方法模式只是用于创建一个对象,这和抽象工厂模式有很大不同。 抽象工厂模式用到了工厂方法模式来创建单一对象,AbstractFactory 中的 cr

  • 工厂方法(Factory Method) Intent 定义了一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法把实例化操作推迟到子类。 Class Diagram 在简单工厂中,创建对象的是另一个类,而在工厂方法中,是由子类来创建对象。 下图中,Factory 有一个 doSomething() 方法,这个方法需要用到一个产品对象,这个产品对象由 factoryMethod() 方法创建。

  • 我想知道在Spring框架中使用依赖注入的工厂模式的当前最佳实践是什么。我想知道工厂模式在使用Spring依赖注入的情况下是否仍然适用。我做了一些搜索,看到了一些过去的讨论(依赖注入vs工厂模式),但似乎有不同的观点。 我在一些现实生活中的项目中看到使用Map来保存所有的bean,并依靠自动装配来创建这些bean。当需要bean时,它使用密钥通过map获取它。 但是我看到这两种方法有些不同。 使用