Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 多DAO不完全实现设计_Java_Spring_Hibernate_Design Patterns_Dao - Fatal编程技术网

Java 多DAO不完全实现设计

Java 多DAO不完全实现设计,java,spring,hibernate,design-patterns,dao,Java,Spring,Hibernate,Design Patterns,Dao,我有spring/hibernate web应用程序。我使用Hibernate来实现几乎所有的DAO。但是,有时我需要使用基于JDBC的实现。对于每个DAO,我都有一个接口,比如说ProductDao',并为其提供了一个实现ProductDaoHibImpl或ProductDaoJdbcImpl。问题是,比如说,如果我有一个带有两个方法的DAO,其中一个方法可以使用Hibernate实现,另一个方法可以使用jdbc实现。最好的班级设计是什么 我想出了这些设计: 一个接口包含两个实现,在每个类中未

我有spring/hibernate web应用程序。我使用Hibernate来实现几乎所有的DAO。但是,有时我需要使用基于JDBC的实现。对于每个DAO,我都有一个接口,比如说ProductDao',并为其提供了一个实现ProductDaoHibImpl或ProductDaoJdbcImpl。问题是,比如说,如果我有一个带有两个方法的DAO,其中一个方法可以使用Hibernate实现,另一个方法可以使用jdbc实现。最好的班级设计是什么

我想出了这些设计:

  • 一个接口包含两个实现,在每个类中未实现的方法中抛出一个运行时异常。(即,当调用hibernate类中实现的方法时,jdbc实现将引发运行时异常)
  • 在一个类中合并两个实现
  • 实现两个类中的所有方法
  • 但是,

    • 设计1是反OO原则
    • 设计2会把整个过程搞砸的 我的DAO实现的一致性,将使类 本身可读性较差,并且会邀请其他开发人员继续添加 方法无组织地对其进行管理
    • 设计3添加了不必要的内容 工作,因为我无论如何都会使用更高效的实现
    对于多个DAO不完整实现,什么是更好的设计

    例如:

    public interface RxDao {
    
        public Rx getRxById(int rxId);
    
        public Map<String, List<Notification>> getAllRxNotificationsGroupedByFacility();
    }
    
    公共接口RxDao{
    公共接收getrxbyd(int rxId);
    公共地图getAllRxNotificationsGroupedByFacility();
    }
    
    getRxById
    使用hibernate实现是有意义的,因为您可以使用hibernate ORM


    另一方面,getAllRxNotificationsGroupedByFacility只检索Rx列的一个子集,但会获取更多的数据,这些数据需要以某种方式分组,并最终发送到另一台服务器,因此使用jdbc实现它更有意义。

    方法2对我来说很好,我不太明白为什么你认为它是两个实现合并在一起的

    对于大多数方法,创建一个使用高级Hibernate功能的DAO是很常见的,但是对于需要它的方法,它会退回到较低的级别。请注意,您可以使用HibernateAPI(本机查询、
    doWork(…)
    等)进行低级访问,因此,将Hibernate与JDBC混合不会带来额外的复杂性

    大概是这样的:

    public class HibernateRxDao implements RxDao {
        ...
    
        public Rx getRxById(int rxId) {
            return sf.getCurrentSession().get(rxId, Rx.class);
        }
    
        public Map<String, List<Notification>> getAllRxNotificationsGroupedByFacility() {
            return toMap(sf.getCurrentSession().createNativeQuery(...). ... .list());
        }
    
        private Map<String, List<Notification>> toMap(List<Object[]> rows) { ... }
    }
    
    公共类HibernateRxDao实现RxDao{
    ...
    公共接收getrxbyd(int rxId){
    返回sf.getCurrentSession().get(rxId,Rx.class);
    }
    公共地图getAllRxNotificationsGroupedByFacility(){
    返回toMap(sf.getCurrentSession().createNativeQuery(…);
    }
    私有映射到映射(列表行){…}
    }
    
    方法2对我来说很好,但是,我不太明白为什么您认为它是两个合并在一起的实现

    对于大多数方法,创建一个使用高级Hibernate功能的DAO是很常见的,但是对于需要它的方法,它会退回到较低的级别。请注意,您可以使用HibernateAPI(本机查询、
    doWork(…)
    等)进行低级访问,因此,将Hibernate与JDBC混合不会带来额外的复杂性

    大概是这样的:

    public class HibernateRxDao implements RxDao {
        ...
    
        public Rx getRxById(int rxId) {
            return sf.getCurrentSession().get(rxId, Rx.class);
        }
    
        public Map<String, List<Notification>> getAllRxNotificationsGroupedByFacility() {
            return toMap(sf.getCurrentSession().createNativeQuery(...). ... .list());
        }
    
        private Map<String, List<Notification>> toMap(List<Object[]> rows) { ... }
    }
    
    公共类HibernateRxDao实现RxDao{
    ...
    公共接收getrxbyd(int rxId){
    返回sf.getCurrentSession().get(rxId,Rx.class);
    }
    公共地图getAllRxNotificationsGroupedByFacility(){
    返回toMap(sf.getCurrentSession().createNativeQuery(…);
    }
    私有映射到映射(列表行){…}
    }
    
    我很好奇为什么需要使用两种不同的模型—Hibernate和JDBC

    我目前正在处理一些类似的事情。我的应用程序将有两个部署,一个使用mySQL,我将自己托管,另一个使用microsoft SQL server,另一家公司将为不同的最终用户组托管


    为了处理我选择作为抽象层的SQL语法中的差异,在经过一点学习之后,我发现它非常容易使用。我可以在Dao对象中设置SQL方言(或使用Servlet init参数),这将是我在两种不同的数据库部署之间唯一需要更改的行。

    我很好奇为什么需要使用两种不同的模型—Hibernate和JDBC

    我目前正在处理一些类似的事情。我的应用程序将有两个部署,一个使用mySQL,我将自己托管,另一个使用microsoft SQL server,另一家公司将为不同的最终用户组托管


    为了处理我选择作为抽象层的SQL语法中的差异,在经过一点学习之后,我发现它非常容易使用。我可以在Dao对象中设置SQL方言(或使用Servlet init参数),这将是我在两种不同的数据库部署之间需要更改的唯一一行。

    如果您仍然希望将事情分开,可以将Dao接口分成两部分(比如说
    JdbcProductOperations
    JpaProductOperations
    )。您的ProductDAO接口不再声明任何方法,而是从这两个接口继承。然后,您可以添加一个ProductDAO实现,该实现采用JdbcProductOperations-和JPAPProductOperations实例,并相应地委托调用。

    如果您仍然希望将事情分开,则可以将DAO接口拆分为ces分成两部分(比如说
    JdbcProductOperations
    JpaProductOperations
    )。您的ProductDAO接口不再声明任何方法,而是从这两个接口继承。然后,您可以添加一个ProductDAO实现,该实现接受JdbcProductOperations-和JPAPProductOperations实例,并相应地委托调用。

    我觉得奇怪的是,您需要
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.HashMap;
    import java.util.Map;
    
    
    public class DaoProxyDemo {
    
        @Target(ElementType.METHOD)
        @Retention(RetentionPolicy.RUNTIME)
        @interface QualityOfService {
            int value();
        }
    
        interface ProductDao {
            String operation1();
            String operation2();
        }
    
        static class JpaProductDao implements ProductDao {
    
            @QualityOfService(1)
            public String operation1() { return "hello from jpa"; }
    
            @QualityOfService(0)
            public String operation2() { throw new UnsupportedOperationException(); }
    
        }
    
        static class JdbcProductDao implements ProductDao {
    
            @QualityOfService(0)
            public String operation1() { throw new UnsupportedOperationException(); }
    
            @QualityOfService(1)
            public String operation2() { return "hello from jdbc"; }
    
        }    
    
        static class QosAwareProxyFactory {
    
            public static <T> T createProxy(Class<T> interfaceType, T... implementations) {
    
                class Binding {
                    private final int qos;
                    private final T impl;
    
                    public Binding(T impl, int qos) {
                        this.impl = impl;
                        this.qos = qos;
                    }
                }
    
                final Map<Method, Binding> dispatchMap = new HashMap<Method, Binding>();
                try {
                    for (Method method : interfaceType.getDeclaredMethods()) {
    
                        for (T impl : implementations) {
    
                            Method implMethod = impl.getClass().getMethod(method.getName(), 
                                    method.getParameterTypes());
    
                            QualityOfService qos = implMethod.getAnnotation(QualityOfService.class);
    
                            int qosValue = qos == null ? 0 : qos.value();
    
                            Binding bestSoFar = dispatchMap.get(method);
    
                            if (bestSoFar == null || bestSoFar.qos < qosValue) {
                                dispatchMap.put(method, new Binding(impl, qos.value()));
                            }
    
                        }
    
                    }
                }
                catch (NoSuchMethodException e) {
                    throw new AssertionError("can never happen");
                }
    
                Object proxy = Proxy.newProxyInstance(QosAwareProxyFactory.class.getClassLoader(), 
                        new Class<?>[] {interfaceType}, new InvocationHandler() {
    
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args)
                            throws Throwable {
    
                        T impl = dispatchMap.get(method).impl;
                        return method.invoke(impl);
                    }
                });
    
                return interfaceType.cast(proxy);
    
            }
        }
    
        public static void main(String[] args) {
    
            ProductDao proxy = QosAwareProxyFactory.createProxy(
                    ProductDao.class, new JpaProductDao(), new JdbcProductDao());
    
            System.out.println(proxy.operation1());
            System.out.println(proxy.operation2());
    
        }
    
    }