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 16. 3Sum Closest JAVA
题目: 给定一个包括n个整数的数组nums和一个目标值target.找到nums中的三个整数,使得他们之和与target最为接近.返回三个整数之和,假定每组输入只存在唯一答案 解题思路: 将nums数 ...
- HTML中DOM元素的子节点为空?!firstChild, lastChild, childeNodes[]为空
- 接口测试:添加cookie以及身份验证
添加cookie以及身份验证的接口文档: cookie:存放在本地的一个键值对 session:存放在服务端的一个键值对 学生金币充值接口文档: 一.使用postman进行测试 由于进行学生金币充值操 ...
- linux使用rsync、inotify-tools实现多台服务器文件实时同步
需求:将本地192.168.1.10上的/data/wwwroot目录同步到 1.来源服务器上安装rsync.inotify-tools yum -y install rsync yum -y ins ...
- P4850 [IOI2009]葡萄干raisins 记忆化搜索
$ \color{#0066ff}{ 题目描述 }$ 普罗夫迪夫的著名巧克力大师Bonny需要切开一板带有葡萄干的巧克力.巧克力是一个包含许多相同的方形小块的矩形.小块沿着巧克力的边排列成n行m列,即 ...
- python cookbook
一 .数据结构 python collections包中 deque :固定长度队列,(例如固定长度的cache什么的) defaultdict:如果每个键值不存在,默认返回值 orderdict:有 ...
- 963 AlvinZH打怪刷经验(背包DP大作战R)
963 AlvinZH打怪刷经验 思路 这不是一道普通的01背包题.大家仔细观察数据的范围,可以发现如果按常理来的话,背包容量特别大,你也会TLE. 方法一:考虑01背包的一个常数优化----作用甚微 ...
- (一)Win消息机制,SDK编程基础
一,基本概念 SDK:软件开发工具包(缩写:SDK.外语全称:Software Development Kit) API:应用程序接口 WINAPI:Windows平台下的系统调用,包含 window ...
- Oracle远程数据建物化视图(materialized)创建简单记录,以及DBLINK的创建
目的:实现远程数据库访问及其相应表的定时同步 一.远程数据库dblink的创建 select * from dba_db_links; select * from user_sys_privs;--查 ...
- 汇编语言_实验四_[bx]和loop的使用
四.实验结论 1. 实验内容1 (1)源代码: assume cs:code code segment mov ax,0b800h mov ds,ax mov bx,07b8h mov c ...