纳税服务系统十一【抽取BaseService、条件查询】
tags: 纳税服务系统项目
抽取BaseService
到目前为止,我们已经写了三个模块的开发了。我们已经抽取过了BaseAction、BaseDao,我们这次来看看我们的Service接口。
- UserService
/*** created by ozc on 2017/5/23.*/
public interface UserService {//新增void save(User user);//更新void update(User user);//根据id删除void delete(Serializable id);//根据id查找User findObjectById(Serializable id);//查找列表List<User> findObjects() throws ServiceException;//导出用户列表void exportExcel(List<User> userList, ServletOutputStream outputStream);//导入用户列表void importExcel(File userExcel, String userExcelFileName);/*** 根据帐号和用户id查询用户** @param id 用户ID* @param account 用户帐号* @return 用户列表*/List<User> findAccount(String id, String account);void saveUserAndRole(User user, String[] userRoleIds);//通过用户id得到该用户的角色List<UserRole> findRoleById(String id);void deleteUserRoleById(String[] userRoleIds);List<User> findUserByAccountAndPassword(String account, String password);
}复制代码
- InfoService
/*** created by ozc on 2017/5/23.*/
public interface InfoService {//新增public void save(Info info);//更新public void update(Info info);//根据id删除public void delete(Serializable id);//根据id查找public Info findObjectById(Serializable id);//查找列表public List<Info> findObjects() ;
}复制代码
- RoleService
/*** Created by ozc on 2017/5/26.*/
public interface RoleService {//新增void save(Role role);//更新void update(Role role);//根据id删除Ovoid delete(Serializable id);//根据id查找Role findObjectById(Serializable id);//查找列表List<Role> findObjects() ;}复制代码
我们可以发现,**三个Service接口中都存在着增删改查的方法,这明显就是重复的代码。**因此,我们需要将他们进行抽取成一个BaseService。
抽取BaseService
在core模块中添加service包,抽取BaseService
package zhongfucheng.core.service;import java.io.Serializable;
import java.util.List;/*** Created by ozc on 2017/6/7.*/
interface BaseService<T> {//新增void save(T entity);//更新void update(T entity);//根据id删除void delete(Serializable id);//根据id查找T findObjectById(Serializable id);//查找列表List<T> findObjects();
}复制代码
- 抽取BaseServiceImpl
我们的Sercive是调用dao层的对象来实现方法的,因为这个Service是代表整个项目的Service,于是应该使用BaseDao
package zhongfucheng.core.service.impl;import zhongfucheng.core.dao.BaseDao;
import zhongfucheng.core.service.BaseService;import java.io.Serializable;
import java.util.List;/*** Created by ozc on 2017/6/7.*/public abstract class BaseServiceImpl <T> implements BaseService <T>{//通过BaseDao来操作数据库private BaseDao<T> baseDao;@Overridepublic void save(T entity) {baseDao.save(entity);}@Overridepublic void update(T entity) {baseDao.update(entity);}@Overridepublic void delete(Serializable id) {baseDao.delete(id);}@Overridepublic T findObjectById(Serializable id) {return baseDao.findObjectById(id);}@Overridepublic List<T> findObjects() {return baseDao.findObjects();}
}复制代码
以Info模块举例子
- InfoService
InfoService继承了BaseService接口,于是就有了增删改查的方法。同时把泛型T的类型确定下来。
/*** created by ozc on 2017/5/23.*/public interface InfoService extends BaseService<Info> {}
复制代码
- InfoServiceImpl
继承了InfoService,有了增删该查的方法,然而具体的操作是BaseServiceImpl中实现的。我们继承它,并给出泛型T对应的类型。
@Service
public class InfoServiceImpl extends BaseServiceImpl<Info> implements InfoService {}复制代码
现在的问题是什么呢???我们在BaseServiceImpl中使用了BaseDao这个变量来对数据库进行操作。可是在BaseServiceImpl中是没有BaseDao这个变量的。
首先,要明确的是,我们不能在BaseServiceImpl中注入BaseDao,因为BaseServiceImpl本身就是一个抽象类。那我们怎么对BaseDao进行实例化呢???
我们可以这样做:
在InfoServiceImpl本身就需要注入InfoDao,来对数据库的操作。
而我们这一次不使用属性输入,使用set方法注入
在注入的同时,在BaseServiceImpl中给BaseDao设置set方法。
那么我们在注入的时候,就可以调用BaseDao的set方法,把我们要注入的对象给过去。
最后,我们在BaseServiceImpl中就有了baseDao这个变量了。
InfoServiceImpl得到InfoDao对象,并把InfoDao对象设置到BaseServiceImpl中。
@Service
public class InfoServiceImpl extends BaseServiceImpl<Info> implements InfoService {private InfoDao infoDao;@Resourcepublic void setInfoDao(InfoDao infoDao) {super.setBaseDao(infoDao);this.infoDao = infoDao;}
}复制代码
- BaseServiceImpl为BaseDao设置set方法。
//通过BaseDao来操作数据库private BaseDao<T> baseDao;public void setBaseDao(BaseDao<T> baseDao) {this.baseDao = baseDao;}复制代码
条件查询
我们来实现下面的功能:
传统方式
其实也是一个查询,只不过查询多了一个条件罢了。按照传统的方式我们可以这样做:
- 在BaseDao中声明一个方法,接收的是SQL和参数列表
//根据条件查询列表List<T> findObjects(String sql, List<Object> objectList);
复制代码
- 在BaseDaoImpl实现它
@Overridepublic List<T> findObjects(String sql, List<Object> objectList) {Query query = getSession().createQuery(sql);if (objectList != null) {int i =0;for (Object o : objectList) {query.setParameter(i, o);i++;}return query.list();}return query.list();}
复制代码
- BaseService定义它:
//根据条件查询列表List<T> findObjects(String sql, List<Object> objectList);复制代码
- BaseServiceImpl中使用baseDao来调用它
@Overridepublic List<T> findObjects(String sql, List<Object> objectList) {return baseDao.findObjects(sql, objectList);}
复制代码
- Action中处理请求
我们还是用着listUI这个方法,因为它仅仅是参数可能不同。
- 如果用户使用的是条件查询,那么它应该有Info对象带过来。
- 如果不是条件查询,就没有Info对象
- 根据Info对象设置是否要设置参数来查询【在HQL语句中添加新字段】。所以这个方法通用。
public String listUI() {//查询语句String hql = "FROM Info i ";List<Object> objectList = new ArrayList<>();//根据info是否为null来判断是否是条件查询。如果info为空,那么是查询所有。if (info != null) {if (StringUtils.isNotBlank(info.getTitle())) {hql += "where i.title like ?";objectList.add("%" + info.getTitle() + "%");}}infoList = infoServiceImpl.findObjects(hql,objectList);ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP);return "listUI";}
复制代码
优化
看回我们Action中的代码,我们可以看出一些不够优雅的地方:
于是,我们想要用一个工具类来把上面的代码进行优化。
针对上面的问题,我们发现手写拼接SQL很容易出错。那我们可以在工具类里面拼接,使用的时候调用方法获取就行啦。查询的对象写死了,我们要可以处理任何的查询。。
我们能够找到如下的规律:
FROM Info WHERE title like ? and state = ? order by createTime,state条件查询(QueryHelper):1、查询条件语句hql:from 子句:必定出现;而且只出现一次where 子句:可选;但关键字where 出现一次;可添加多个查询条件order by子句:可选;但关键字order by 出现一次;可添加多个排序属性2、查询条件值集合:出现时机:在添加查询条件的时候,?对应的查询条件值复制代码
- 工具类代码:
package zhongfucheng.core.utils;import java.util.ArrayList;
import java.util.List;/*** Created by ozc on 2017/6/7.*/
public class QueryHelper {private String fromClause = "";private String whereClause = "";private String orderbyClause = "";private List<Object> objectList;public static String ORDER_BY_ASC = "asc";public static String ORDER_BY_DESC = "desc";//FROM子句只出现一次/*** 构建FROM字句,并设置查询哪张表* @param aClass 用户想要操作的类型* @param alias 别名*/public QueryHelper(Class aClass, String alias) {fromClause = " FROM " + aClass.getSimpleName() + " " + alias;}//WHERE字句可以添加多个条件,但WHERE关键字只出现一次/*** 构建WHERE字句* @param condition* @param objects* @return*/public QueryHelper addCondition(String condition, Object... objects) {//如果已经有字符了,那么就说明已经有WHERE关键字了if (whereClause.length() > 0) {whereClause += " AND " + condition;} else {whereClause += " WHERE" + condition;}//在添加查询条件的时候,?对应的查询条件值if (objects == null) {objectList = new ArrayList<>();}for (Object object : objects) {objectList.add(object);}return this;}/**** @param property 要排序的属性* @param order 是升序还是降序* @return*/public QueryHelper orderBy(String property, String order) {//如果已经有字符了,那么就说明已经有ORDER关键字了if (orderbyClause.length() > 0) {orderbyClause += " , " + property +" " + order;} else {orderbyClause += " ORDER BY " + property+" " + order;}return this;}/*** 返回HQL语句*/public String returnHQL() {return fromClause + whereClause + orderbyClause;}/*** 得到参数列表* @return*/public List<Object> getObjectList() {return objectList;}
}复制代码
- Action处理:
public String listUI() {QueryHelper queryHelper = new QueryHelper(Info.class, "i");//根据info是否为null来判断是否是条件查询。如果info为空,那么是查询所有。if (info != null) {if (StringUtils.isNotBlank(info.getTitle())) {queryHelper.addCondition(" i.title like ? ", "%" + info.getTitle() + "%");}}queryHelper.orderBy("i.createTime", QueryHelper.ORDER_BY_DESC);infoList = infoServiceImpl.findObjects(queryHelper);//infoList = infoServiceImpl.findObjects(hql,objectList);ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP);return "listUI";}
复制代码
- 最后在dao、service层中添加一个queryHelper参数的方法就行了。
总结
- 由于Service的代码重复性太高了,我们也将Service进行抽取。抽取成一个BaseService接口
- BaseServiceImpl实现BaseService接口,但他要使用BaseDao对象来对实现的方法进行调用
- 此时,BaseServiceImpl是一个抽象类,它本身不能实例化了。那怎么将BaseDao实例化呢??
- 当我们的InfoServiceImpl继承继承着BaseServiceImpl时,本身就需要用到InfoDao来对该模块的业务进行调用。
- 在InfoServiceImpl对InfoDao实例话是很容易的,可以使用自动装配,set方法注入等等。这次我们使用set方法注入!
- set方法有什么好处??能够在InfoServiceImpl注入InfoDao对象的同时,还能进行其他操作。比如:调用父类的set方法!!!!!!!
- 我们只要在BaseServiceImpl提供一个setBaseDao方法,子类再把自身的Dao传递进去。那么我们的BaseDao就被实例化了!
- 由于我们查询条件的不确定性,要对查询条件字符串进行拼接。这样不安全和很容易出错。我们就封装了一个查询助手对象。专门用于查询的。
如果您觉得这篇文章帮助到了您,可以给作者一点鼓励
纳税服务系统十一【抽取BaseService、条件查询】相关推荐
- 纳税服务系统【总结】
纳税服务系统总结 纳税服务系统是我第一个做得比较大的项目(不同于javaWeb小项目),该项目系统来源于传智Java32期,十天的视频课程(想要视频的同学关注我的公众号就可以直接获取了) 我跟着练习一 ...
- java纳税服务_纳税服务系统【总结】
纳税服务系统总结 纳税服务系统是我第一个做得比较大的项目(不同于javaWeb小项目),该项目系统来源于传智Java32期,十天的视频课程(想要视频的同学关注我的公众号就可以直接获取了) 我跟着练习一 ...
- JAVA缴税_纳税服务系统【总结】
纳税服务系统总结 纳税服务系统是我第一个做得比较大的项目(不同于javaWeb小项目),该项目系统来源于传智Java32期,十天的视频课程(想要视频的同学关注我的公众号就可以直接获取了) 我跟着练习一 ...
- java纳税服务_纳税服务系统总结
纳税服务系统总结 纳税服务系统是我第一个做得比较大的项目(不同于javaWeb小项目),该项目系统来源于传智Java32期,十天的视频课程(想要视频的同学关注我的公众号就可以直接获取了) 我跟着练习一 ...
- 纳税服务系统八【系统、子系统首页】
tags: 纳税服务系统项目 前言 到目前位置,我们的用户模块和角色模块基本已经做好了,我们的纳税服务系统是放在一个大系统里边的.我们应该把我们已经写好的模块加载进去. 加载整个系统首页 导入对应的J ...
- 免费视频直播点播服务器系统,搭建一套完整的网络视频流媒体直播/点播服务系统需要具备哪些条件?...
原标题:搭建一套完整的网络视频流媒体直播/点播服务系统需要具备哪些条件? 随着Internet的飞速发展,网上现场直播已经从实验阶段走向了实用阶段.各式各样的社会活动都可以借助网上现场直播方式传遍全世 ...
- 纳税服务系统【系统、子系统首页】
前言 到目前位置,我们的用户模块和角色模块基本已经做好了,我们的纳税服务系统是放在一个大系统里边的.我们应该把我们已经写好的模块加载进去. 加载整个系统首页 导入对应的JSP页面: 创建home模块的 ...
- 纳税服务系统四(角色模块)【角色与权限、角色与用户】
需求分析 我们直接来看看原型图,看看需求是怎么样的: 这里写图片描述 这里写图片描述 我们看到上图,就会发现角色模块主要还是CRUD,唯一不同的就是它不再是单独的实体关系.角色与权限是存在关系的. 之 ...
- 纳税服务系统【角色模块、包含权限】
需求分析 我们直接来看看原型图,看看需求是怎么样的: 我们看到上图,就会发现角色模块主要还是CRUD,唯一不同的就是它不再是单独的实体关系.角色与权限是存在关系的. 之前在Servlet+JSP+Ja ...
最新文章
- 5分钟 搭建免费个人博客
- 2017年重要数据安全事件解读
- 《SQL Server 2012 T-SQL基础》读书笔记 - 1.背景
- Linux免密登陆(CentOS7.2为例)
- java并发策略_Java并发(六):并发策略
- c语言xml字符串,C语言的XML解析器
- C++ STL中哈希表 hash_map介绍
- 交通与计算机杂志社,交通信息与安全
- Vivado debug异常现象
- 在VC中使用Delphi构造公共对话框
- Tableau可视化学习笔记:day13-14
- Visual Studio 2010 中编写C代码的一些常见问题
- Linux系统教学-Lesson01
- Snagit 2021\2022
- 市面上主流RTC竞品对比分析
- 数据分析神器Alteryx
- 数字字符串转为数字 C语言实现
- mysql 主键列_MySQL列属性 之 主键
- 【安卓】给ViewFlipper加指示器,类似ViewPagerIndicator库提供的那种、!
- 18年春石油大学多媒体技术在线作业(一)(二)答案