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;
}
4.提取后的CustomerDao
public interface CustomerDao extends BaseDao<Customer> {
}
5. 提取后的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;
}
6. 如果这样抽取完成以后,那么在编写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层
Javaee的Dao层的抽取的更多相关文章
- 案例50-crm练习dao层的抽取BaseDao
1 抽取BaseDao 2 BaseDao设计思路 3 BaseDao接口书写 package www.test.dao; import java.io.Serializable; import ja ...
- javaEE中关于dao层和services层的理解
javaEE中关于dao层和services层的理解 入职已经一个多月了,作为刚毕业的新人,除了熟悉公司的项目,学习公司的框架,了解项目的一些业务逻辑之外,也就在没学到什么:因为刚入职, 带我的那个师 ...
- 系统管理模块_部门管理_改进_抽取添加与修改JSP页面中的公共代码_在显示层抽取BaseAction_合并Service层与Dao层
系统管理模块_部门管理_改进1:抽取添加与修改JSP页面中的公共代码 commons.jspf <%@ page language="java" import="j ...
- springboot 注册dao层 service 层
可以使用三种注解来引入DAO层的接口到spring容器中.1.@Mapper,写在每一个DAO层接口上,如下: 2.@MapperScan和@ComponentScan两者之一.前者的意义是将指定包中 ...
- Java高并发秒杀API之业务分析与DAO层
根据慕课网上关于java高并发秒杀API的课程讲解用maven+ssm+redis实现的一个秒杀系统 参考了codingXiaxw's blog,很详细:http://codingxiaxw.cn/2 ...
- DAO层注入HibernateTemplate的两种方式
-------------------------siwuxie095 DAO 层注入 HibernateTemplat ...
- DAO 层实现
一.实验介绍 1.1 实验内容 本节课程主要利用 MyBatis 框架实现 DAO 层. 1.2 实验知识点 MyBatis 框架 MySQL 1.3 实验环境 JDK1.8 Eclipse Java ...
- Mybatis的dao层实现 接口代理方式实现规范+plugins-PageHelper
Mybatis的dao层实现 接口代理方式实现规范 Mapper接口实现时的相关规范: Mapper接口开发只需要程序员编写Mapper接口而不用具体实现其代码(相当于我们写的Imp实现类) Mapp ...
- Mybatis的Dao层实现原理
1.Mybatis的Dao层实现 1.1 传统开发方式 1.1.1编写UserDao接口 public interface UserDao { List<User> findAll() t ...
随机推荐
- THUSC2017酱油记
啊..酱油记三连发.. 果然SHTSC用掉太多RP了.. 其实感觉没什么好写的..都被考懵逼了.. 但还是写一下吧.. DAY0 月考完提前一天到了..什么也没发生 DAY1 先考试再开幕式..好奇怪 ...
- java的排序算法
分享网页:https://yq.aliyun.com/articles/136085?utm_content=m_26483
- dict字典;dict的操作
一.字典: 1. 字典 dict 用{}来表示 键值对数据 {key:value} 唯一性 键 都必须是可哈希的 不可变的数据类型就可以当做字典中的键 值 没有任何限制 1.1 字典的创建: ...
- String,数组,list集合长度的使用
public class Use{ public static void main(String[] args){ int[] arr=new int[]{19,10,20,30,23,13}; // ...
- 集合之五:Set接口
set接口的简单介绍 set接口在API中的说明是:一个不包含重复元素的 collection.更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 ...
- paraview鼠标选择网格
虽然可以根据ID选择网格,但是有时候需要选择可见面,直接鼠标比较方便,可以直接按一下键盘"S",这时候鼠标变成十字型,然后鼠标左键选择区域.
- AXI协议(一)
最近弄Zynq,不懂AXI协议Zynq很难玩儿的转.这些笔记主要攻克AXI中的一些难题. 所有的AXI4包含了5个不同的通道: (1)读/写地址通道(Read/Write address ch ...
- V1-bug Alpha阶段项目展示
V1-bug Alpha阶段项目展示 团队成员简介 Name Summary Sefie wxmwy V1-bug制造公司资深工程师精通各种抱大腿方式团队吉祥物 182 面面俱到流派一丝不苟 Powe ...
- ORACLE MERGE INTO UPDATE DELETE 用法
ORACLE MERGE INTO UPDATE DELETE 用法 使用该MERGE语句从一个或多个源中选择行以进行更新或插入表或视图.您可以指定条件以确定是更新还是插入目标表或视图. 此语句是组合 ...
- SQL基础语法select|insert|update|delete(增删改查) 简单使用
以下案列以此表举例 1.select(查询) select简单的查询分为两种 注:字段也就是表结构中的列的名称 第一种: select 字段名 from 表名 此种查询只列出你所需要查询的字段, ...