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 ...
随机推荐
- leetcode 45. 跳跃游戏 II JAVA
题目: 给定一个非负整数数组,你最初位于数组的第一个位置. 数组中的每个元素代表你在该位置可以跳跃的最大长度. 你的目标是使用最少的跳跃次数到达数组的最后一个位置. 示例: 输入: [2,3,1,1, ...
- offsetWidth和width的区别
1.offsetWidth属性可以返回对象的padding+border+width属性值之和,style.width返回值就是定义的width属性值. 2.offsetWidth属性仅是可读属性,而 ...
- 洛谷P5245 【模板】多项式快速幂
题面 传送门 题解 话说现在还用数组写多项式的似乎没几个了-- \[B(x)=A^k(x)\] \[\ln B(x)=k\ln A(x)\] 求个\(\ln\),乘个\(k\),\(\exp\)回去就 ...
- 扩展欧拉定理【洛谷P4139】 上帝与集合的正确用法
P4139 上帝与集合的正确用法 \(2^{2^{2^{\dots}}}\bmod p\) 卡最优解倒数第一祭. 带一下扩展欧拉定理就好了. code: #include <iostream&g ...
- 7.pytest中的 plugin
一直想弄弄清这里的东西,一直各种因素delay,今天务必要搞搞清 一.先从官方文档上尝试去解读下什么是plugin和hook 网上有现成的对你适用的插件时候,我们可以直接pip安装,拿来使用即可:但是 ...
- IDEA 直接点击运行执行正常,命令行下面执行Jar包出现部分乱码的情况。
解决方案如上: 有个Springboot项目为了测试方便,模型类用中文作为字段属性,封装成Odata格式,在通过Springboot发布并打成jar包. 通过命令行启动jar包里面的Springweb ...
- MySql 的操作日志 历史记录
如何查看mysql数据库操作记录日志 1.首先确认你日志是否启用了mysql>show variables like 'log_bin'. 2.如果启用了,即ON,那日志文件就在mysql的安装 ...
- 修改ZuulHandlerMapping私有变量pathMatcher,重写match方法,使url匹配兼容正则表达式。
一.起源 在mocksever中引入了spring cloud zuul做代理转发,如果请求的url和配置的mock规则匹配(精确匹配和模糊匹配),忽略,不做转发.如果mock配置的url和请求url ...
- python全栈开发_day5_字符串及列表类型
一:字符串 1)优先掌握知识点. a=" 21j3:b12jk:b3j12:3bjk12 " #内置方法之strip print(a.strip(" ")) # ...
- 2018牛客多校6 - I Team Rocket KD树维护空间
题意:给出n条铁路区间\([L,R]\),共有m个boom依时间顺序放置在\(k_i\)中,区间与\(k_i\)有交集的都被炸掉 求每次炸掉的铁路个数和最后输出所有id被炸的时间点 炸弹能炸到的区间满 ...