美文网首页程序员
在Hibernate中,我们来浅谈一下泛型DAO

在Hibernate中,我们来浅谈一下泛型DAO

作者: 浑身演技 | 来源:发表于2016-08-16 20:15 被阅读150次

    背景:最近项目组同事希望大家一起写一个泛型DAO,然后大家可以一起使用。

    作为项目组中拥有审核代码权限的人,我认为,至少在使用Hibernate这个对象关系映射框架中,是不必要的。而我之所以反对的原因是

    • 业务模型是复杂多变的,我们很难从其中抽取出共同的抽象类(有的业务模型十分复杂,有的业务模型简单,这些情况将会导致对于业务简单DAO层类需要继承很多不必要的方法)。

    • Hibernate对于对象关系映射已经封装的很好,没必要再写一个类似Hibernate关系对象映射的封装了。

    • 抽象出来的DAO类很难复用,将会导致各个模块有着相同的业务逻辑。(举例来说,成员A写了一个用户模块(该用户模块只处理自己的业务逻辑:如用户权限控制,用户状态),成员B在完成订单模块的同时,需要用户模块的时候,是可以调用用户模块A,但是会面临着成员A会对用户模块进行重写的风险,往往为了规避这种风险存在,成员B就会对这个用户模块进行再次复写。这种大量重复的开发的确存在着)。

    也正是因为以上的观点,我想出了一种基于抽象工厂、适配器的混合设计模式 。

    Talk is cheap,show me the code

    // DAO的工厂接口
    public interface DaoFactory<T,P> {
        // 取消注册
        public void unrgistered(T type);
        // 注册
        public void register(T type,P provider);
        // 更新
        public void update(T type, P provider);
         // 获取
        public P valueOf(T type);
    }
    
    // DAO的适配器
    @FunctionalInterface
    public interface DaoProvider<T> {
        public T of();
    }
    
    // DAO的类型
    public interface DaoType {}
    
    // DAO的抽象工厂
    public abstract class AbstractDaoFactory<T extends DaoType,P extends DaoProvider<?>> implements DaoFactory<T,P>{
        protected static final Map<DaoType, DaoProvider<?>> map = new ConcurrentHashMap<>(4);
        @Override
        public void register(T type,P provider){
            Objects.requireNonNull(type);
            Objects.requireNonNull(provider);
            if (map.containsKey(type))
                throw new DaoRegisteredException();
            map.putIfAbsent(type, provider);
        }
        @Override
        public void unrgistered(T type){
            Objects.requireNonNull(type);
    
            if (!map.containsKey(type))
                throw new DaoUnregisteredException();
            map.remove(type);
        }
        @Override
        public void update(T type, P provider){
            Objects.requireNonNull(type);
            Objects.requireNonNull(provider);
    
            if (!map.containsKey(type))
                throw new DaoUpdatedException();
    
            map.replace(type, provider);
        }
        @SuppressWarnings("unchecked")
        @Override
        public P valueOf(T type){
            Objects.requireNonNull(type);
    
            if (!map.containsKey(type))
                throw new DaoUnregisteredException();
            return (P) map.get(type);
        }    
    }
    
    public class DaoRegisteredException extends RuntimeException {
        private static final long serialVersionUID = -3794217705148674984L;
    
        public DaoRegisteredException() {
            super("Dao has registered,using update method please...");
        }
    
        public DaoRegisteredException(String message, Throwable cause, boolean enableSuppression,
                boolean writableStackTrace) {
            super(message, cause, enableSuppression, writableStackTrace);
        }
    
        public DaoRegisteredException(String message, Throwable cause) {
            super(message, cause);
        }
    
        public DaoRegisteredException(String message) {
            super(message);
        }
    
        public DaoRegisteredException(Throwable cause) {
            super(cause);
        }
        
    }
    
    public class DaoUnregisteredException extends RuntimeException {
        private static final long serialVersionUID = 5997668949853885283L;
    
        public DaoUnregisteredException() {
            super("Dao still unregistered,using register method please...");
        }
    
        public DaoUnregisteredException(String message, Throwable cause, boolean enableSuppression,
                boolean writableStackTrace) {
            super(message, cause, enableSuppression, writableStackTrace);
        }
    
        public DaoUnregisteredException(String message, Throwable cause) {
            super(message, cause);
        }
    
        public DaoUnregisteredException(String message) {
            super(message);
        }
    
        public DaoUnregisteredException(Throwable cause) {
            super(cause);
        }
        
    }
    
    public class DaoUpdatedException extends RuntimeException {
        private static final long serialVersionUID = -1424730522134154582L;
    
        public DaoUpdatedException() {
            super("Dao still unregisted,using register method please...");
        }
    
        public DaoUpdatedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
            super(message, cause, enableSuppression, writableStackTrace);
        }
    
        public DaoUpdatedException(String message, Throwable cause) {
            super(message, cause);
        }
    
        public DaoUpdatedException(String message) {
            super(message);
        }
    
        public DaoUpdatedException(Throwable cause) {
            super(cause);
        }
        
    }
    
    

    这里,我提供了DaoFactory的接口(注册,取消注册,更新Dao适配器与获取适配器等方法),并且同时提供了DAO的适配器、DAO的类型。

    同时在AbstractDaoFactory中,我对其进行了简单的实现。到了这里,其实大家可以看出,我就是对于一个抽象模型的增删查改的DAO进行拆分。因为我现在设计的这些类要解决的就是上面的三个问题。

    • 任何一个业务模型CURD必须细分出来,不需要继承不必要的抽象类,必须注册到DaoFactory中去。

    • 不需要你去写适应项目组成员的泛型Dao。

    • 你所实现的方法是可以给别人调用,因为当你需要进行重构你的代码的时候,你只能新增方法,不能修改你原先的业务逻辑。其他成员将会将会根据你的DaoType进行索引你的方法。

    简单应用案例:

    @SuppressWarnings("rawtypes")
    public interface HotelOrderDetailDaoProvider extends DaoProvider<HotelOrderDetailQueryDao>{}
    
    @FunctionalInterface
    public interface HotelOrderDetailQueryDao<T> {
        public T queryHotelOrderDetail(int id);
    }
    
    
    public final class HotelOrderDetailDaoFactory extends AbstractDaoFactory<HotelOrderDetailType,HotelOrderDetailDaoProvider> implements DaoFactory<HotelOrderDetailType,HotelOrderDetailDaoProvider>{
        private static final Logger log=LoggerFactory.getLogger(HotelOrderDetailDaoFactory.class);
        private static final HotelOrderDetailDaoFactory factory=new HotelOrderDetailDaoFactory();
        private HotelOrderDetailDaoFactory(){
            log.info("HotelOrderDaoFactory start accepting registration...");
        }
        /**
         * @return
         */
        public static HotelOrderDetailDaoFactory getInstance() {
            return factory;
        }
    }
    
    

    Thanks for reading,have a good night :)

    相关文章

      网友评论

        本文标题:在Hibernate中,我们来浅谈一下泛型DAO

        本文链接:https://www.haomeiwen.com/subject/xpwpsttx.html