热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

详解JavaeeDao层的抽取

这篇文章主要介绍了详解JavaeeDao层的抽取,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

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

一、提取前

1. 提取前的LinkDao层:

public interface LinkManDao {

  Integer findCount(DetachedCriteria detachedCriteria);

  List 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 list = (List) hibernateTemplate.findByCriteria(detachedCriteria);
    if(list != null && list.size() > 0) {
      return list.get(0).intValue();
    }
    return null;
  }

  @Override
  public List findByPage(DetachedCriteria detachedCriteria, Integer startIndex, Integer pageSize) {
    detachedCriteria.setProjection(null);
    return (List) 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 findByPage(DetachedCriteria detachedCriteria, Integer startIndex, Integer pageSize);
  Customer findById(Long cust_id);
  void delete(Customer customer);
  void update(Customer customer);
  List findAll();
}

4.提取前的CustomerDaoImpl

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

  /**
   * Dao层保存客户信息实现方法
   * 

Title: CustomerDaoImpl

*

Description:

* @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 list = (List) hibernateTemplate.findByCriteria(detachedCriteria); if(list != null && list.size() > 0) { return list.get(0).intValue(); } return null; } //根据查询条件查询总页数 @Override public List findByPage(DetachedCriteria detachedCriteria, Integer startIndex, Integer pageSize) { //由于在统计总记录数的时候已经修改了发送的SQL语句,在此需要需要清空 detachedCriteria.setProjection(null); return (List) 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 findAll() { return (List) hibernateTemplate.find("from Customer"); } }

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

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

1. BaseDao层

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

2. BaseDaoImpl层

public class BaseDaoImpl implements BaseDao {
  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 findAll() {
    return (List) hibernateTemplate.find("from "+ this.clazz.getSimpleName());
  }
  //查询Count(*)行记录数
  @Override
  public Integer findCount(DetachedCriteria detachedCriteria) {
    detachedCriteria.setProjection(Projections.rowCount());
    List list = (List) hibernateTemplate.findByCriteria(detachedCriteria);
    if(list != null && list.size() > 0) {
      return list.get(0).intValue();
    }
    return null;
  }
  //分页查询信息
  @Override
  public List findByPage(DetachedCriteria detachedCriteria, Integer startIndex, Integer pageSize) {
    detachedCriteria.setProjection(null);
    return (List) hibernateTemplate.findByCriteria(detachedCriteria, startIndex, pageSize);
  }

}

3. 提取后的LinkManDao

public interface LinkManDao extends BaseDao{

}

4. 提取后的LinkManDaoImpl

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

  @Autowired
  private HibernateTemplate hibernateTemplate;
}

5.提取后的CustomerDao

public interface CustomerDao extends BaseDao {

}

6. 提取后的CustomerDaoImpl

@Repository
public class CustomerDaoImpl extends BaseDaoImpl 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称为类型参数变量

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

ArrayList  :ArrayList称为参数化类型

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

泛型反射的步骤:

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

第二步:查看API

  

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

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

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

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

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

2. 代码实现

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

public class BaseDaoImpl implements BaseDao {
  private Class clazz;
  //提供构造方法,在构造方法中让继承的子类向方法中传入具体类型Class
  /**
   * 不想子类上有构造方法,必须在父类中提供无参的构造,在无参构造中获取具体的类型Class
   * 具体类型中的Class是参数类型中的实际类型 参数
   */
  public BaseDaoImpl() {
    //反射:第一步获得Class
    Class clazz = this.getClass();//正在被调用的那个类的Class,CustomerDaoImpl或LinkManDaoImpl
    //具体查看JDK的API
    Type type = clazz.getGenericSuperclass();//参数化类型BaseDaoImpl,BaseDaoImpl
    //得到的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 findAll() {
    return (List) hibernateTemplate.find("from "+ this.clazz.getSimpleName());
  }
  //查询Count(*)行记录数
  @Override
  public Integer findCount(DetachedCriteria detachedCriteria) {
    detachedCriteria.setProjection(Projections.rowCount());
    List list = (List) hibernateTemplate.findByCriteria(detachedCriteria);
    if(list != null && list.size() > 0) {
      return list.get(0).intValue();
    }
    return null;
  }
  //分页查询信息
  @Override
  public List findByPage(DetachedCriteria detachedCriteria, Integer startIndex, Integer pageSize) {
    detachedCriteria.setProjection(null);
    return (List) hibernateTemplate.findByCriteria(detachedCriteria, startIndex, pageSize);
  }

}

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

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

  @Autowired
  private HibernateTemplate hibernateTemplate;
}

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

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

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

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


推荐阅读
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • Startup 类配置服务和应用的请求管道。Startup类ASP.NETCore应用使用 Startup 类,按照约定命名为 Startup。 Startup 类:可选择性地包括 ... [详细]
  • 本文深入探讨了SQL数据库中常见的面试问题,包括如何获取自增字段的当前值、防止SQL注入的方法、游标的作用与使用、索引的形式及其优缺点,以及事务和存储过程的概念。通过详细的解答和示例,帮助读者更好地理解和应对这些技术问题。 ... [详细]
  • 本章详细介绍SP框架中的数据操作方法,包括数据查找、记录查询、新增、删除、更新、计数及字段增减等核心功能。通过具体示例和详细解析,帮助开发者更好地理解和使用这些方法。 ... [详细]
  • 配置PHPStudy环境并使用DVWA进行Web安全测试
    本文详细介绍了如何在PHPStudy环境下配置DVWA( Damn Vulnerable Web Application ),并利用该平台进行SQL注入和XSS攻击的练习。通过此过程,读者可以熟悉常见的Web漏洞及其利用方法。 ... [详细]
  • 最新计算机专业原创毕业设计参考选题都有源码+数据库是近期作品ling取参考你的选题刚好在下面有,有时间看到机会给您发1ssm资源循环利用2springboot校园考勤系统3ssm防 ... [详细]
  • PHP 编程疑难解析与知识点汇总
    本文详细解答了 PHP 编程中的常见问题,并提供了丰富的代码示例和解决方案,帮助开发者更好地理解和应用 PHP 知识。 ... [详细]
  • 本文详细介绍了如何使用libpq库与PostgreSQL后端建立连接。通过探讨PQconnectdb()函数的工作原理及其在实际应用中的使用方法,帮助读者理解并掌握建立高效、稳定的数据库连接的关键步骤。 ... [详细]
  • Windows服务与数据库交互问题解析
    本文探讨了在Windows 10(64位)环境下开发的Windows服务,旨在定期向本地MS SQL Server (v.11)插入记录。尽管服务已成功安装并运行,但记录并未正确插入。我们将详细分析可能的原因及解决方案。 ... [详细]
  • SQL中UPDATE SET FROM语句的使用方法及应用场景
    本文详细介绍了SQL中UPDATE SET FROM语句的使用方法,通过具体示例展示了如何利用该语句高效地更新多表关联数据。适合数据库管理员和开发人员参考。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • SQLite 动态创建多个表的需求在网络上有不少讨论,但很少有详细的解决方案。本文将介绍如何在 Qt 环境中使用 QString 类轻松实现 SQLite 表的动态创建,并提供详细的步骤和示例代码。 ... [详细]
  • Hadoop入门与核心组件详解
    本文详细介绍了Hadoop的基础知识及其核心组件,包括HDFS、MapReduce和YARN。通过本文,读者可以全面了解Hadoop的生态系统及应用场景。 ... [详细]
  • 本文介绍如何在 FireDAC 环境下实现 FDMEMTable 字段的自动获取,为开发人员提供便捷的数据处理方式。 ... [详细]
  • 利用SSH隧道实现外网对局域网机器的安全访问
    本文探讨了一种常见的网络配置问题及其解决方案,即如何在外网环境下安全地访问位于局域网内的计算机。特别介绍了使用SSH反向隧道技术来实现这一目标的具体步骤和注意事项。 ... [详细]
author-avatar
baaiiii
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有