热门标签 | 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 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • 本章详细介绍SP框架中的数据操作方法,包括数据查找、记录查询、新增、删除、更新、计数及字段增减等核心功能。通过具体示例和详细解析,帮助开发者更好地理解和使用这些方法。 ... [详细]
  • 配置PHPStudy环境并使用DVWA进行Web安全测试
    本文详细介绍了如何在PHPStudy环境下配置DVWA( Damn Vulnerable Web Application ),并利用该平台进行SQL注入和XSS攻击的练习。通过此过程,读者可以熟悉常见的Web漏洞及其利用方法。 ... [详细]
  • 最新计算机专业原创毕业设计参考选题都有源码+数据库是近期作品ling取参考你的选题刚好在下面有,有时间看到机会给您发1ssm资源循环利用2springboot校园考勤系统3ssm防 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • PHP 5.2.5 安装与配置指南
    本文详细介绍了 PHP 5.2.5 的安装和配置步骤,帮助开发者解决常见的环境配置问题,特别是上传图片时遇到的错误。通过本教程,您可以顺利搭建并优化 PHP 运行环境。 ... [详细]
  • 构建基于BERT的中文NL2SQL模型:一个简明的基准
    本文探讨了将自然语言转换为SQL语句(NL2SQL)的任务,这是人工智能领域中一项非常实用的研究方向。文章介绍了笔者在公司举办的首届中文NL2SQL挑战赛中的实践,该比赛提供了金融和通用领域的表格数据,并标注了对应的自然语言与SQL语句对,旨在训练准确的NL2SQL模型。 ... [详细]
  • 本文详细介绍了HTML中标签的使用方法和作用。通过具体示例,解释了如何利用标签为网页中的缩写和简称提供完整解释,并探讨了其在提高可读性和搜索引擎优化方面的优势。 ... [详细]
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • 本文深入探讨 MyBatis 中动态 SQL 的使用方法,包括 if/where、trim 自定义字符串截取规则、choose 分支选择、封装查询和修改条件的 where/set 标签、批量处理的 foreach 标签以及内置参数和 bind 的用法。 ... [详细]
  • WinSCP: 跨Windows与Linux系统的高效文件传输解决方案
    本文详细介绍了一款名为WinSCP的开源图形化SFTP客户端,该工具支持SSH协议,适用于Windows操作系统,能够实现与Linux系统之间的文件传输。对于从事嵌入式开发的技术人员来说,掌握WinSCP的使用方法将极大提高工作效率。 ... [详细]
  • 利用SSH隧道实现外网对局域网机器的安全访问
    本文探讨了一种常见的网络配置问题及其解决方案,即如何在外网环境下安全地访问位于局域网内的计算机。特别介绍了使用SSH反向隧道技术来实现这一目标的具体步骤和注意事项。 ... [详细]
  • 在Linux系统上构建Web服务器的详细步骤
    本文详细介绍了如何在Linux系统上搭建Web服务器的过程,包括安装Apache、PHP和MySQL等关键组件,以及遇到的一些常见问题及其解决方案。 ... [详细]
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社区 版权所有