详解Javaee Dao层的抽取

有时候我们在实现不同功能的时候回看到很多的Dao层的增加、修改、删除、查找都很相似,修改我们将他们提取BaseDao

一、提取前

1. 提取前的LinkDao层:

public interface LinkManDao {

  Integer findCount(DetachedCriteria detachedCriteria);

  List<LinkMan> findByPage(DetachedCriteria detachedCriteria, Integer startIndex, Integer pageSize);

  void save(LinkMan linkMan);

  LinkMan findById(Long lkm_id);

  void update(LinkMan linkMan);

  void delete(LinkMan linkMan);

}

2. 提取前的LinkDaoImpl:

@Repository
public class LinkManDaoImpl implements LinkManDao {
  @Autowired
  private HibernateTemplate hibernateTemplate;

  @Override
  public Integer findCount(DetachedCriteria detachedCriteria) {
    //select count(*) from LinkMan
    detachedCriteria.setProjection(Projections.rowCount());
    List<Long> list = (List<Long>) hibernateTemplate.findByCriteria(detachedCriteria);
    if(list != null && list.size() > 0) {
      return list.get(0).intValue();
    }
    return null;
  }

  @Override
  public List<LinkMan> findByPage(DetachedCriteria detachedCriteria, Integer startIndex, Integer pageSize) {
    detachedCriteria.setProjection(null);
    return (List<LinkMan>) hibernateTemplate.findByCriteria(detachedCriteria, startIndex, pageSize);
  }

  @Override
  public void save(LinkMan linkMan) {
    hibernateTemplate.save(linkMan);
  }
  //Dao层根据id查找联系人
  @Override
  public LinkMan findById(Long lkm_id) {
    return hibernateTemplate.get(LinkMan.class, lkm_id);
  }
  //Dao层更新联系人信息
  @Override
  public void update(LinkMan linkMan) {
    hibernateTemplate.update(linkMan);
  }
  //Dao层删除联系人
  @Override
  public void delete(LinkMan linkMan) {
    hibernateTemplate.delete(linkMan);
  }
}

3. 提取前的CustomerDao

public interface CustomerDao{
  void save(Customer customer);
  Integer findCount(DetachedCriteria detachedCriteria);
  List<Customer> findByPage(DetachedCriteria detachedCriteria, Integer startIndex, Integer pageSize);
  Customer findById(Long cust_id);
  void delete(Customer customer);
  void update(Customer customer);
  List<Customer> findAll();
}

4.提取前的CustomerDaoImpl

@Repository
public class CustomerDaoImpl implements CustomerDao {
  //注入hibernateTemplate模板
  @Autowired
  private HibernateTemplate hibernateTemplate;

  /**
   * Dao层保存客户信息实现方法
   * <p>Title: CustomerDaoImpl</p>
   * <p>Description: </p>
   * @param customer
   * @see com.sshcrm.dao.CustomerDao#saveCustomer(com.sshcrm.pojo.Customer)
   */
  @Override
  public void saveCustomer(Customer customer) {
    hibernateTemplate.save(customer);
  }
  //根据条件查询结果集的总记录数
  @Override
  public Integer findCount(DetachedCriteria detachedCriteria) {
    //select count(*) from Customer
    detachedCriteria.setProjection(Projections.rowCount());
    List<Long> list = (List<Long>) hibernateTemplate.findByCriteria(detachedCriteria);
    if(list != null && list.size() > 0) {
      return list.get(0).intValue();
    }
    return null;
  }
  //根据查询条件查询总页数
  @Override
  public List<Customer> findByPage(DetachedCriteria detachedCriteria, Integer startIndex, Integer pageSize) {
    //由于在统计总记录数的时候已经修改了发送的SQL语句,在此需要需要清空
    detachedCriteria.setProjection(null);
    return (List<Customer>) hibernateTemplate.findByCriteria(detachedCriteria, startIndex, pageSize);
  }
  @Override
  public Customer findById(Long cust_id) {
    return hibernateTemplate.get(Customer.class, cust_id);
  }
  @Override
  public void delete(Customer customer) {
    hibernateTemplate.delete(customer);
  }
  @Override
  public void update(Customer customer) {
    hibernateTemplate.update(customer);
  }
  @Override
  public List<Customer> findAll() {
    return (List<Customer>) hibernateTemplate.find("from Customer");
  }
}

5.可以看到CustomerDaoImpl和LinkManDaoImpl方法很相似,所以需要提取

二、利用在子类中传递真正的Class类型来提取BaseDao,编写泛型

1. BaseDao层

public interface BaseDao<T> {
  void save(T t);
  void update(T t);
  void delete(T t);
  public T findById(Serializable id);
  public List<T> findAll();
  public Integer findCount(DetachedCriteria detachedCriteria);
  public List<T> findByPage(DetachedCriteria detachedCriteria, Integer startIndex, Integer pageSize);
}

2. BaseDaoImpl层

public class BaseDaoImpl<T> implements BaseDao<T> {
  private Class clazz;
  //提供构造方法,在构造方法中让继承的子类向方法中传入具体类型Class
  public BaseDaoImpl(Class clazz) {
    this.clazz = clazz;
  }
  //注入HibernateTemplate模板
  @Autowired
  private HibernateTemplate hibernateTemplate;
  //保存信息
  @Override
  public void save(T t) {
    hibernateTemplate.save(t);
  }
  //更新信息
  @Override
  public void update(T t) {
    hibernateTemplate.update(t);
  }
  //删除信息
  @Override
  public void delete(T t) {
    hibernateTemplate.delete(t);
  }
  //根据id查询信息
  @Override
  public T findById(Serializable id) {
    return (T) hibernateTemplate.get(this.clazz, id);
  }
  //查询所有信息
  @Override
  public List<T> findAll() {
    return (List<T>) hibernateTemplate.find("from "+ this.clazz.getSimpleName());
  }
  //查询Count(*)行记录数
  @Override
  public Integer findCount(DetachedCriteria detachedCriteria) {
    detachedCriteria.setProjection(Projections.rowCount());
    List<Long> list = (List<Long>) hibernateTemplate.findByCriteria(detachedCriteria);
    if(list != null && list.size() > 0) {
      return list.get(0).intValue();
    }
    return null;
  }
  //分页查询信息
  @Override
  public List<T> findByPage(DetachedCriteria detachedCriteria, Integer startIndex, Integer pageSize) {
    detachedCriteria.setProjection(null);
    return (List<T>) hibernateTemplate.findByCriteria(detachedCriteria, startIndex, pageSize);
  }

}

3. 提取后的LinkManDao

public interface LinkManDao extends BaseDao<LinkMan>{

}

4. 提取后的LinkManDaoImpl

@Repository
public class LinkManDaoImpl extends BaseDaoImpl<LinkMan> implements LinkManDao {

  //提供构造参数,在构造方法中传入具体类型的Class
  public LinkManDaoImpl() {
    super(LinkMan.class);
  }

  @Autowired
  private HibernateTemplate hibernateTemplate;
}

5.提取后的CustomerDao

public interface CustomerDao extends BaseDao<Customer> {

}

6. 提取后的CustomerDaoImpl

@Repository
public class CustomerDaoImpl extends BaseDaoImpl<Customer> implements CustomerDao {

  //提供构造参数,在构造方法中传入具体的Class
  public CustomerDaoImpl() {
    super(Customer.class);
    // TODO Auto-generated constructor stub
  }

  //注入hibernateTemplate模板
  @Autowired
  private HibernateTemplate hibernateTemplate;
}

7.  如果这样抽取完成以后,那么在编写DAO的时候如果里面都是一些CRUD的操作,在DAO中只需要提供构造方法即可。

三、如果将通用的DAO编写的更好,连构造方法都不想要了!!!需要怎么做???  泛型反射

1 解决方案二:通过泛型的反射抽取通用的DAO

l  如果现在将DAO中的构造方法去掉,将父类的通用的DAO中提供无参数的构造即可,但是需要在无参数的构造中需要获得具体类型的Class才可以-----涉及到泛型的反射了。

l  回顾一下泛型:

泛型         :通用的类型。

<>             :念为  typeof

List<E>     :E称为类型参数变量

ArrayList<Integer>  :Integer称为是实际类型参数

ArrayList<Integer>  :ArrayList<Integer>称为参数化类型

需要做的时候在父类的构造方法中获得子类继承父类上的参数化类型中的实际类型参数

泛型反射的步骤:

第一步:获得代表子类对象的Class

第二步:查看API

  

Type[] getGenericInterfaces();        :获得带有泛型的接口,可以实现多个接口。

Type getGenericSuperclass();          :获得带有泛型的父类,继承一个类。

第三步:获得带有泛型的父类

第四步:将带有泛型的父类的类型转成具体参数化的类型

第五步:通过参数化类型的方法获得实际类型参数

2. 代码实现

2.1 修改BaseDaoImpl里面的无参构造方法:

public class BaseDaoImpl<T> implements BaseDao<T> {
  private Class clazz;
  //提供构造方法,在构造方法中让继承的子类向方法中传入具体类型Class
  /**
   * 不想子类上有构造方法,必须在父类中提供无参的构造,在无参构造中获取具体的类型Class
   * 具体类型中的Class是参数类型中的实际类型 参数
   */
  public BaseDaoImpl() {
    //反射:第一步获得Class
    Class clazz = this.getClass();//正在被调用的那个类的Class,CustomerDaoImpl或LinkManDaoImpl
    //具体查看JDK的API
    Type type = clazz.getGenericSuperclass();//参数化类型BaseDaoImpl<Customer>,BaseDaoImpl<LinkMan>
    //得到的type就是一个参数化类型,将type强转为参数化类型
    ParameterizedType pType = (ParameterizedType) type;
    //通过参数化类型获得实际类型参数,得到一个实际类型参数的数组
    Type[] types = pType.getActualTypeArguments();
    //只获得第一参数类型即可
    this.clazz = (Class) types[0];//得到Customer,LinkMan
  }
  //注入HibernateTemplate模板
  @Autowired
  private HibernateTemplate hibernateTemplate;
  //保存信息
  @Override
  public void save(T t) {
    hibernateTemplate.save(t);
  }
  //更新信息
  @Override
  public void update(T t) {
    hibernateTemplate.update(t);
  }
  //删除信息
  @Override
  public void delete(T t) {
    hibernateTemplate.delete(t);
  }
  //根据id查询信息
  @Override
  public T findById(Serializable id) {
    return (T) hibernateTemplate.get(this.clazz, id);
  }
  //查询所有信息
  @Override
  public List<T> findAll() {
    return (List<T>) hibernateTemplate.find("from "+ this.clazz.getSimpleName());
  }
  //查询Count(*)行记录数
  @Override
  public Integer findCount(DetachedCriteria detachedCriteria) {
    detachedCriteria.setProjection(Projections.rowCount());
    List<Long> list = (List<Long>) hibernateTemplate.findByCriteria(detachedCriteria);
    if(list != null && list.size() > 0) {
      return list.get(0).intValue();
    }
    return null;
  }
  //分页查询信息
  @Override
  public List<T> findByPage(DetachedCriteria detachedCriteria, Integer startIndex, Integer pageSize) {
    detachedCriteria.setProjection(null);
    return (List<T>) hibernateTemplate.findByCriteria(detachedCriteria, startIndex, pageSize);
  }

}

2.2 现在LinkDao和CustomerDao不用改变,修改LinkDaoImpl和CustomerDaoImpl

@Repository
public class LinkManDaoImpl extends BaseDaoImpl<LinkMan> implements LinkManDao {
  //提供构造参数,在构造方法中传入具体的Class
/*  public LinkManDaoImpl() {
    super(LinkMan.class);
  }*/

  @Autowired
  private HibernateTemplate hibernateTemplate;
}
@Repository
public class CustomerDaoImpl extends BaseDaoImpl<Customer> implements CustomerDao {
  //提供构造参数,在构造方法中传入具体的Class
  /*public CustomerDaoImpl() {
    super(Customer.class);
    // TODO Auto-generated constructor stub
  }*/

  //注入hibernateTemplate模板
  @Autowired
  private HibernateTemplate hibernateTemplate;
}

2.3 后面如果Dao层有特殊方法是可以在比如CustomerDaoImpl中去实现,相似的就不需要了,以此来到达抽取Dao层

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 通过代理类实现java连接数据库(使用dao层操作数据)实例分享

    首先,我们在一个java文件中定义要存储的结构类型: 复制代码 代码如下: import java.util.Date ;/** * * @author Nero */public class Emp {    private int empno ;    private String ename ;    private String job ;    private Date hiredate ;    private float sal ;    public void setEmpno(

  • 详解Javaee Dao层的抽取

    有时候我们在实现不同功能的时候回看到很多的Dao层的增加.修改.删除.查找都很相似,修改我们将他们提取BaseDao 一.提取前 1. 提取前的LinkDao层: public interface LinkManDao { Integer findCount(DetachedCriteria detachedCriteria); List<LinkMan> findByPage(DetachedCriteria detachedCriteria, Integer startIndex, Int

  • 详解JavaEE使用过滤器实现登录(用户自动登录 安全登录 取消自动登录黑用户禁止登录)

    在我们生活中,对于账户的自动登录已经很常见了,所以利用过滤器实现这个功能. 主要介绍用户的自动登录和取消自动登录,以及实现一天自动登录或者n天实现自动登录,当用户ip被加入到黑名单之后,直接利用过滤器返回一个警告页面. 过滤器的功能很是强大,我们只需要在写好的前台后servlet之后进行添加就可以实现这个功能 Ps:这个仅仅只是一个演示而已,里面的访问数据库的部分,自己随意模拟了下,主要是突出实现自动登录的功能. 前台代码: 前台代码是成功与否都在这个页面显示.用到的技术:jstl标签的应用,s

  • 详解JavaEE中Apollo安装使用小结

    目录 一.安装MySQL5.7.37(主机:192.168.233.128,用户/密码:root): 二.Apollo安装/启动(centos7)(主机:192.168.233.128): 三.Web应用接入Apollo(SpringBoot): 说明: Apollo是配置管理中心,和SpringCloud-Config实现的功能有点相似. 一.安装MySQL 5.7.37(主机:192.168.233.128,用户/密码:root): 1.下载mysql-5.7.37-1.el7.x86_64

  • jQuery遮罩层实现方法实例详解(附遮罩层插件)

    本文实例分析了jQuery遮罩层实现方法.分享给大家供大家参考,具体如下: 1 背景半透明遮罩层样式 需要一个黑色(当然也可以其他)背景,且须设置为绝对定位,以下是项目中用到的css样式: /* 半透明的遮罩层 */ #overlay { background: #000; filter: alpha(opacity=50); /* IE的透明度 */ opacity: 0.5; /* 透明度 */ display: none; position: absolute; top: 0px; lef

  • 详解JAVAEE——SSH三大框架整合(spring+struts2+hibernate)

    一.整合原理 二.导包(41个) 1.hibernate (1)hibernate/lib/required (2)hibernate/lib/jpa | java persist api java的持久化规范(接口) (3)数据库驱动 2.struts2 (1)struts-blank.war/WEB-INF/lib/* 注意:javassist-3.18.1-GA.jar包与hibernate中的重复(只保留高版本即可) (2)struts整合spring插件包 注意:这个包一旦导入,那么s

  • 详解Django模板层过滤器和继承的问题

    过滤器 模板层对变量的操作实际还有很多,过滤器就是其中一种.学过Linux系统的一定知道管道操作符,其可以将上一步输出直接作为下一步输入进行处理,这里的过滤器就是类似管道符,其写法也是以管道符|为标志,允许我们对模板层获得的变量进行改变,例如大小写转换.增减大小等等 语法 {{ 变量|过滤器1|过滤器2:'值' |...}} 这里的过滤器可以分为两类,一类是不带参数的,例如lower,upper,safe:一类是带参数的add:'10',冒号分隔,后面跟上值 过滤器 示例 说明 lower {{

  • 详解JavaEE 使用 Redis 数据库进行内容缓存和高访问负载

    NoSQL(Not Only SQL),泛指非关系型数据库,是为了处理高并发读写.海量数据的高效率存储和访问.高扩展性和高可用性而产生的. 分类 相关产品 典型应用 数据模型 优点 缺点 键值对(Key-Value)存储 Redis.Voldemort.Berkeley DB 内容缓存.处理高访问负载 一系列键值对 快速查询 存储的数据缺少结构化 列存储数据库 Cassandra.HBase.Riak 分布式文件系统 以列簇式存储,将同一列数据存在一起 查询速度快,可扩展性强,更容易进行分布式扩

  • Spring MVC自定义日期类型转换器实例详解

    Spring MVC自定义日期类型转换器实例详解 WEB层采用Spring MVC框架,将查询到的数据传递给APP端或客户端,这没啥,但是坑的是实体类中有日期类型的属性,但是你必须提前格式化好之后返回给它们.说真的,以前真没这样做过,之前都是一口气查询到数据,然后在jsp页面上格式化,最后展示给用户.但是这次不同,这次我纯属操作数据,没有页面.直接从数据库拿数据给它们返数据.它们给我传数据我持久化数据,说到这里一个小问题就默默的来了. 首先把问题还原一下吧(这是一个数据导出功能),下图中用红框圈

  • SpringData JPA基本/高级/多数据源的使用详解

    目录 一.SpringDataJPA基本用法 1.概念 JPA由来 JPA是什么 SpringDataJPA 2.快速上手 1.添加依赖 2.添加配置文件 3.实体类 4.Repository构建 5.测试 6.基本查询 7.自定义查询 3.小结 二.SpringDataJPA高级用法 1.自定义SQL查询 2.分页查询SpringDataJPA已经帮我们内置了分页功能 3.复杂查询 4.多表查询 5.小结 三.SpringDataJPA多数据源使用 1.前言 2.多数据源的支持 3.小结 一.

  • Java Mybatis框架Dao层的实现与映射文件以及核心配置文件详解分析

    目录 Mybatis的Dao层实现 传统开发方式 代理开发方式 MyBatis映射文件深入 动态sql语句 动态SQL之<if> 动态SQL之<foreach> SQL片段抽取 总结 Mybatis核心配置文件深入 typeHandlers标签 plugins标签 总结 Mybatis的Dao层实现 传统开发方式 1.编写UserDao接口 public interface UserMapper { public List<User> findAll() throws

随机推荐