【OA】——DAO层设计

简介: 【OA】——DAO层设计

引言


之前总是在使用别人搭建好的架构来实现具体的业务,没有真正的思考架构设计的原因,基于什么样的原因要采用这样的架构,为什么在底层使用了那么多的接口、抽象类等等,现在在搭建OA系统的DAO时候意识到了这方面的原因,下面就来总结一下。

 

首先来看一下最后的设计类图:



20170216112250447.png

原来我们在设计的时候都知道面向接口编程,所以在DAO层都有一个接口,这样我们就不在需要将dao层的具体实现暴露给调用者,但是我们并没有考虑抽象将公共的方法放在一个父接口中,因为我们有很多的公共的方法,比方说:对于每一个实体我们都至少有四个方法——增、删、该、查等,在上面我们抽取了6个公共的方法。这样的话我们就很好的避免在每一个接口中都定义增删该查的方法。这样每一个具体业务的接口都去继承这个父接口就好了。

 

下面我们就来分析一下抽象类的这个问题,我们为什么会增加了一个抽象类?这就需要我们了解接口和抽象类概念和解决什么样的问题,在数据库的操作我们采用的hibernate来实现的,所以在实现增删该查的代码是是一样的,只是我们操作的实体不同,所以这里就要用到反射的技术来拿到我们具体操作的实体的类型。如果我们比较了解反射技术的话,这就非常好理解了。然后具体的实现类继承这个抽象类,这样对于公共方法的实现就可以抽象到这个类里面来实现,所有的公共的方法的只有一个实现。  

 

也就是我们具体的实现类在继承了抽象类以后,还要实现一个接口?这是因为那些和具体业务逻辑有关的方法需要在具体的接口里面声明,我们只是将公共的方法放在了baseDao里面。

 

下面来看一下怎样利用泛型+反射来实现抽象类的中方法的实现?

 

接口中的代码:

package cn.itcast.oa.base.dao;
import java.util.List;
public interface DaoSupport<T> {
  /**
   * 保存实体
   * 
   * @param entity
   */
  void save(T entity);
  /**
   * 删除实体
   * 
   * @param entity
   */
  void delete(Long id);
  /**
   * 更新实体
   * 
   * @param entity
   */
  void update(T entity);
  /**
   * 通过id查询
   * 
   * @param id
   * @return
   */
  T getById(Long id);
  /**
   * 根据ids 返回实体集合
   * 
   * @param ids
   * @return
   */
  List<T> getByIds(Long[] ids);
  /**
   * 获得所有数据集合
   * 
   * @return
   */
  List<T> findAll();
}


抽象类中的代码?

package cn.itcast.oa.base.dao;
import java.lang.reflect.ParameterizedType;
import java.util.Collections;
import java.util.List;
import javax.annotation.Resource;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Transactional;
@SuppressWarnings("unchecked")
@Transactional
public abstract class DaoSupportImpl<T> implements DaoSupport<T> {
  @Resource
  protected SessionFactory sessionFactory;
  private Class<T> clazz;
  public DaoSupportImpl() {
    // 使用反射技术得到T的真实类型
    ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass(); // 获取当前new的对象的
                                              // 泛型的父类
                                              // 类型
    this.clazz = (Class<T>) pt.getActualTypeArguments()[0]; // 获取第一个类型参数的真实类型
    System.out.println("clazz ---> " + clazz);
  }
  /**
   * 获取当前可用的Session
   * 
   * @return
   */
  protected Session getSession() {
    return sessionFactory.getCurrentSession();
  }
  public void save(T entity) {
    getSession().save(entity);
  }
  public void update(T entity) {
    getSession().update(entity);
  }
  public void delete(Long id) {
    Object obj = getById(id);
    if (obj != null) {
      getSession().delete(obj);
    }
  }
  public T getById(Long id) {
    if (id == null) {
      return null;
    } else {
      return (T) getSession().get(clazz, id);
    }
  }
  public List<T> getByIds(Long[] ids) {
    if (ids == null || ids.length == 0) {
      return Collections.EMPTY_LIST;
    } else {
      return getSession().createQuery(//
          "FROM " + clazz.getSimpleName() + " WHERE id IN (:ids)")//
          .setParameterList("ids", ids)//
          .list();
    }
  }
  public List<T> findAll() {
    return getSession().createQuery(//
        "FROM " + clazz.getSimpleName())//
        .list();
  }
}


上面也是对于反射的一个典型的应用了,其实反射就是一种动态的生成过程,有的时候在编译期间,并不知道应该去impot那一个class。只能通过一一些方法拿到一个名字的时候,就需要考虑用反射类做了。  


小结


其实我们在很多的源码中都是这么设计的,对于抽象类和接口应用的非常的灵活,这样就可以使我们的代码非常的简介并且灵活,这些也是需要我们在平常学习过程中非常值得研究的一块内容。

目录
相关文章
|
存储 Dart 数据库
Flutter笔记:状态提升、控制器模式、GetX控制器和服务
Flutter笔记:状态提升、控制器模式、GetX控制器和服务
911 0
|
缓存 JavaScript 前端开发
Java 如何确保 JS 不被缓存
大家好,我是 V 哥。本文探讨了 Java 后端确保 JavaScript 不被缓存的问题,分析了文件更新后无法生效、前后端不一致、影响调试与开发及安全问题等场景,并提供了使用版本号、设置 HTTP 响应头、配置静态资源缓存策略和使用 ETag 等解决方案。最后讨论了缓存的合理使用及其平衡方法。
306 0
|
监控 Go API
Go语言在微服务架构中的应用实践
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出,成为构建微服务的理想选择。本文将探讨Go语言在微服务架构中的应用实践,包括Go语言的特性如何适应微服务架构的需求,以及在实际开发中如何利用Go语言的特性来提高服务的性能和可维护性。我们将通过一个具体的案例分析,展示Go语言在微服务开发中的优势,并讨论在实际应用中可能遇到的挑战和解决方案。
|
存储 机器学习/深度学习 缓存
MemLong: 基于记忆增强检索的长文本LLM生成方法
本文介绍了一种名为MemLong的创新长文本处理方法,该方法通过整合外部检索器显著增强了大型语言模型处理长上下文的能力。MemLong采用轻量级设计,利用不可训练的外部记忆库存储历史上下文和知识,并通过检索相关的块级键值对增强模型输入。其技术优势包括分布一致性、高效训练策略及扩展的上下文窗口,能够在单个GPU上处理长达80k个token的文本,同时保持计算效率和内存控制。实验结果显示,MemLong在多个长文本基准数据集上表现出色,显著提升了语言建模能力和上下文学习效果。
1125 1
|
分布式计算 数据安全/隐私保护
高通量计算框架HTCondor(三)——使用命令
高通量计算框架HTCondor(三)——使用命令
263 0
|
NoSQL 前端开发 测试技术
👀探秘微服务:从零开启网关 SSO 服务搭建之旅
单点登录(Single Sign-On,简称SSO)是一种认证机制,它允许用户只需一次登录就可以访问多个应用程序或系统。本文结合网关和SaToken快速搭建可用的Session管理服务。
990 8
|
程序员 Go API
Go语言微服务框架 - 10.接口文档-openapiv2的在线文档方案
随着项目的迭代,一个服务会开放出越来越多的接口供第三方调用。 虽然`protobuf`已经是通用性很广的IDL文件了,但对于未接触过这块的程序员来说,还是有很大的学习成本。在综合可读性和维护性之后,我个人比较倾向于使用oepnapiv2的方案,提供在线接口文档。
381 0
|
JSON 编解码 中间件
go-zero代码生成器助你高效开发
go-zero代码生成器助你高效开发
|
分布式计算 NoSQL Spark
技术好文:scyllaDB基本使用
技术好文:scyllaDB基本使用
|
安全 Linux 数据安全/隐私保护
Nomad 系列 -Nomad+Traefik+Tailscale 集成实现零信任安全
Nomad 系列 -Nomad+Traefik+Tailscale 集成实现零信任安全