美文网首页程序员
在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

    背景:最近项目组同事希望大家一起写一个泛型DAO,然后大家可以一起使用。 作为项目组中拥有审核代码权限的人,我认为...

  • java 范型 Hibernate Jackson的一些应用和思

    Hibernate 范型基类通用DAO的解释Hibernate 基类DAO接口 import java.io.S...

  • Kotlin:泛型和委托

    前言 本篇文章我们来学一下泛型和委托,Kotlin中的泛型跟java中的泛型有同有异,而委托则是一个新的概念,发车...

  • Java高级特性-泛型:泛型的基本用法,怎样才能少写 1 万行代

    泛型是 Java 的一个高级特性。在 Mybatis、Hibernate 这种持久化框架,泛型更是无处不在。 然而...

  • [ WWDC2018 ] - Swift 泛型 Swift Ge

    Swift 泛型历史 我们首先来回顾一下 Swift 中对于泛型支持的历史变更,看看现在在 Swift 中,泛型都...

  • Kotlin:泛型杂谈(下)

    在Kotlin:泛型杂谈(上)中,从泛型扩展属性、非空约束、实例化类型参数三个方面简单介绍了一下Kotlin中泛型...

  • 注解

    作用: 在类中定义泛型: 在方法中定义泛型: 给泛型设置通配符上限: 给泛型设置通配符下限: 泛型擦除: 兼容性:...

  • java泛型详解

    泛型是Java中一个非常重要的知识点,在Java集合类框架中泛型被广泛应用。本文我们将从零开始来看一下Java泛型...

  • TS 泛型+装饰器

    typescript 中的泛型 泛型的定义泛型函数泛型类泛型接口 泛型:软件工程中,我们不仅要创建一致的定义良好的...

  • Kotlin之泛型的实化、协变、逆变

    1、泛型的实化 Java中泛型是在JDK1.5引入的,是一个伪泛型,它是通过泛型擦除机制来实现的。泛型只存在编译时...

网友评论

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

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