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、条件查询】相关推荐

  1. 纳税服务系统【总结】

    纳税服务系统总结 纳税服务系统是我第一个做得比较大的项目(不同于javaWeb小项目),该项目系统来源于传智Java32期,十天的视频课程(想要视频的同学关注我的公众号就可以直接获取了) 我跟着练习一 ...

  2. java纳税服务_纳税服务系统【总结】

    纳税服务系统总结 纳税服务系统是我第一个做得比较大的项目(不同于javaWeb小项目),该项目系统来源于传智Java32期,十天的视频课程(想要视频的同学关注我的公众号就可以直接获取了) 我跟着练习一 ...

  3. JAVA缴税_纳税服务系统【总结】

    纳税服务系统总结 纳税服务系统是我第一个做得比较大的项目(不同于javaWeb小项目),该项目系统来源于传智Java32期,十天的视频课程(想要视频的同学关注我的公众号就可以直接获取了) 我跟着练习一 ...

  4. java纳税服务_纳税服务系统总结

    纳税服务系统总结 纳税服务系统是我第一个做得比较大的项目(不同于javaWeb小项目),该项目系统来源于传智Java32期,十天的视频课程(想要视频的同学关注我的公众号就可以直接获取了) 我跟着练习一 ...

  5. 纳税服务系统八【系统、子系统首页】

    tags: 纳税服务系统项目 前言 到目前位置,我们的用户模块和角色模块基本已经做好了,我们的纳税服务系统是放在一个大系统里边的.我们应该把我们已经写好的模块加载进去. 加载整个系统首页 导入对应的J ...

  6. 免费视频直播点播服务器系统,搭建一套完整的网络视频流媒体直播/点播服务系统需要具备哪些条件?...

    原标题:搭建一套完整的网络视频流媒体直播/点播服务系统需要具备哪些条件? 随着Internet的飞速发展,网上现场直播已经从实验阶段走向了实用阶段.各式各样的社会活动都可以借助网上现场直播方式传遍全世 ...

  7. 纳税服务系统【系统、子系统首页】

    前言 到目前位置,我们的用户模块和角色模块基本已经做好了,我们的纳税服务系统是放在一个大系统里边的.我们应该把我们已经写好的模块加载进去. 加载整个系统首页 导入对应的JSP页面: 创建home模块的 ...

  8. 纳税服务系统四(角色模块)【角色与权限、角色与用户】

    需求分析 我们直接来看看原型图,看看需求是怎么样的: 这里写图片描述 这里写图片描述 我们看到上图,就会发现角色模块主要还是CRUD,唯一不同的就是它不再是单独的实体关系.角色与权限是存在关系的. 之 ...

  9. 纳税服务系统【角色模块、包含权限】

    需求分析 我们直接来看看原型图,看看需求是怎么样的: 我们看到上图,就会发现角色模块主要还是CRUD,唯一不同的就是它不再是单独的实体关系.角色与权限是存在关系的. 之前在Servlet+JSP+Ja ...

最新文章

  1. 5分钟 搭建免费个人博客
  2. 2017年重要数据安全事件解读
  3. 《SQL Server 2012 T-SQL基础》读书笔记 - 1.背景
  4. Linux免密登陆(CentOS7.2为例)
  5. java并发策略_Java并发(六):并发策略
  6. c语言xml字符串,C语言的XML解析器
  7. C++ STL中哈希表 hash_map介绍
  8. 交通与计算机杂志社,交通信息与安全
  9. Vivado debug异常现象
  10. 在VC中使用Delphi构造公共对话框
  11. Tableau可视化学习笔记:day13-14
  12. Visual Studio 2010 中编写C代码的一些常见问题
  13. Linux系统教学-Lesson01
  14. Snagit 2021\2022
  15. 市面上主流RTC竞品对比分析
  16. 数据分析神器Alteryx
  17. 数字字符串转为数字 C语言实现
  18. mysql 主键列_MySQL列属性 之 主键
  19. 【安卓】给ViewFlipper加指示器,类似ViewPagerIndicator库提供的那种、!
  20. 18年春石油大学多媒体技术在线作业(一)(二)答案

热门文章

  1. NIST 人脸识别竞赛 FRVT(Face Recognition Vendor Test)
  2. python opencv 保存摄像头视频,以及fourc编码的介绍
  3. opencv、matplotlib、pillow和pytorch读取数据的通道顺序
  4. es中的DiscoveryModule
  5. java中的深浅拷贝
  6. PHP学习系列(1)——字符串处理函数(3)
  7. 使用字符流 创建文件 写入文件 复制文件
  8. 获取当前应用程序的文件名
  9. 【python】点分十进制ip与数字互转
  10. 词频统计-------------web版本