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 ...
随机推荐
- Jquery中each
1.选择器+遍历 $('div').each(function (i){ i就是索引值 this 表示获取遍历每一个dom对象 }); 2.选择器+遍历 $('div').each(function ...
- IE9以下不支持placeholder属性
jquery.placeholder.min.js 这个js可以去这个网站搜索https://www.bootcdn.cn/jquery-placeholder/ 使用这个jquery.placeho ...
- QTREE5 - Query on a tree V(LCT)
题意翻译 你被给定一棵n个点的树,点从1到n编号.每个点可能有两种颜色:黑或白.我们定义dist(a,b)为点a至点b路径上的边个数. 一开始所有的点都是黑色的. 要求作以下操作: 0 i 将点i的颜 ...
- codis__通用的使用模式
1,按功能模块分成不同的productName 参照 sample_user, sample_dynamic (见附件) sample_user.tar.gz,sample_dynamic.tar.g ...
- this指向的一个小总结
凡是在函数内部调用的函数的this的指向都是window 定时器,延时器this的指向都是window 在事件中一般情况下this的指向都指向当前的DOM对象 在对象函数中this的指向一般情况下都指 ...
- 【洛谷 5002】专心OI - 找祖先 (树上计数)
专心OI - 找祖先 题目背景 \(Imakf\)是一个小蒟蒻,他最近刚学了\(LCA\),他在手机\(APP\)里看到一个游戏也叫做\(LCA\)就下载了下来. 题目描述 这个游戏会给出你一棵树,这 ...
- [redis] 数据特性简单实验
位图 由bit位组成的数组,实际的底层数组类型是字符串,而字符串的本质是二进制大对象,所以将其视作位图,位图存储的是boolean指,一定程度上可以减少存储空间. -- 设置位图指定偏移量的比特位的值 ...
- JavaScript DOM编程艺术 笔记(二)语句操作
操作 var total = (1+4)*5; year = year +1; year++; var message = "i am" + "girl"; 是 ...
- 机器学习中的范数规则化之 L0、L1与L2范数、核范数与规则项参数选择
装载自:https://blog.csdn.net/u012467880/article/details/52852242 今天我们聊聊机器学习中出现的非常频繁的问题:过拟合与规则化.我们先简单的来理 ...
- [原创]Redis 持久化说明及配置
目录 参考链接 介绍 RDB 持久化 优点 缺点 相关配置参数 AOF 持久化 优点 缺点 相关配置参数 参考链接 持久化 Redis命令参考 介绍 Redis 运行时数据保存在内存中, 一旦重启则数 ...