抽取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删除O
void 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; @Override
public void save(T entity) {
baseDao.save(entity); } @Override
public void update(T entity) {
baseDao.update(entity); } @Override
public void delete(Serializable id) {
baseDao.delete(id); }
@Override
public T findObjectById(Serializable id) {
return baseDao.findObjectById(id);
} @Override
public 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;
@Resource
public 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实现它

@Override
public 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来调用它

@Override
public 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参数的方法就行了。

纳税服务系统【抽取BaseService、条件查询】的更多相关文章

  1. 纳税服务系统【信息发布管理、Ueditor、异步信息交互】

    需求分析 我们现在来到了纳税服务系统的信息发布管理模块,首先我们跟着原型图来进行需求分析把: 一些普通的CRUD,值得一做的就是状态之间的切换了.停用和发布切换. 值得注意的是:在信息内容中,它可以带 ...

  2. 纳税服务系统【异常处理、抽取BaseAction】

    前言 本博文主要讲解在项目中异常是怎么处理的.一般我们都不会直接把后台异常信息返回给用户,用户是看不懂的.让用户看见一大串的错误代码,这是不合理的.因此我们需要对报错进行处理. 我们在开发的时候是使用 ...

  3. 纳税服务系统【统计图Fusionchart】

    需求 我们在投诉模块中还有一个功能没有实现: 统计:根据年度将相应年度的每个月的投诉数进行统计,并以图表的形式展示在页面中:在页面中可以选择查看当前年度及其前4年的投诉数.在页面中可以选择不同的年度, ...

  4. 纳税服务系统【自动受理,Quartz任务调度】

    需求 回到我们的需求: 自动投诉受理:在每个月月底最后一天对本月之前的投诉进行自动处理:将投诉信息的状态改为 已失效.在后台管理中不能对该类型投诉进行回复. 这个需求需求我们要怎么弄呢????要在每个 ...

  5. 纳税服务系统【用户模块之使用POI导入excel、导出excel】

    前言 再次回到我们的用户模块上,我们发现还有两个功能没有完成: 对于将网页中的数据导入或导出到excel文件中,我们是完全没有学习过的.但是呢,在Java中操作excel是相对常用的,因此也有组件供我 ...

  6. JavaWeb系统(增删改查、多条件查询功能)

    该系统是一个简单的青年服务管理系统,主要包括了较完整的常用的增删改查以及多条件查询功能,对于初学者有很大帮助. 下面是相关的Java代码.jsp页面.以及数据库的创建和相关表的设计 java代码 首先 ...

  7. PLSQL显示乱码-无法进行中文条件查询解决

    PLSQL显示乱码-无法进行中文条件查询解决 原因: PLSQL乱码问题皆是ORACLE服务端字符集编码与PLSQL端字符集编码不一致引起.类似乱码问题都可以从编码是否一致上面去考虑. 解决: 1. ...

  8. 动态多条件查询分页以及排序(一)--MVC与Entity Framework版url分页版

    一.前言 多条件查询分页以及排序  每个系统里都会有这个的代码 做好这块 可以大大提高开发效率  所以博主分享下自己的6个版本的 多条件查询分页以及排序 二.目前状况 不论是ado.net 还是EF ...

  9. MongoDB 组合多个条件查询($and、$in、$gte、$lte)

    一,问题描述 数据格式: id, timeStamp,count 条件1:查询 某个时间段 内的数据: timeStamp BETWEEN startTime AND endTime.比如 timeS ...

随机推荐

  1. 我读<代码整洁之道>--读书笔记整理

    第一章 整洁代码 "我可以列出我留意到的整洁代码的所有特点,但其中有一条是根本性的,整洁的代码总是看起来像是某位特别在意他的人写的.几乎没有改进的余地,代码作者设么都想到了,如果你企图改进它 ...

  2. noip提高组2011 Mayan游戏

    Mayan游戏 描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个7行5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.**游戏通关 ...

  3. wmic 获得系统硬件信息

    wmic扩展了wmi系统管理指令,提供了命令行接口和批处理执行系统管理的工具.通过别名机制将命令转为对wmi命名空间的操作 1.获得cpu信息 2.获得cpu 核数 3.获得内存条信息

  4. View.post() 不靠谱的地方你知道吗?

    版权声明: 本账号发布文章均来自公众号,承香墨影(cxmyDev),版权归承香墨影所有. 每周会统一更新到这里,如果喜欢,可关注公众号获取最新文章. 未经允许,不得转载. 一.前言 有时候,我们会需要 ...

  5. [目标检测]PVAnet原理

    创新点:基于Faster-RCNN使用更高效的基础网络 1.1 创新点 PVAnet是RCNN系列目标方向,基于Faster-RCNN进行改进,Faster-RCNN基础网络可以使用ZF.VGG.Re ...

  6. windows 10 安装tensorflow

    人工智能一浪接一浪,随着谷歌公布tensorflow源码,尤其是支持windows 10平台的python3.5以上版本,更是让更多人都想用windows操作tensorflow. 第一次安装,也不知 ...

  7. python+selenium自动化软件测试(第9章) :Logging模块

    9.1 Logging模块 什么是日志记录?记录是跟踪运行时发生的事件的一种手段.该软件的开发人员将记录调用添加到其代码中,以指示某些事件已发生.事件由描述性消息描述,该消息可以可选地包含可变数据(即 ...

  8. MySQL下载安装、基本配置、问题处理

    一 mysql介绍 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下公司.MySQL 最流行的关系型数据库管理系统,在 WEB 应用方面MySQL是 ...

  9. Javascript用数组实现栈和队列

    栈是遵循后进先出(LIFO)规则的一种有序集合,比如桌上的一叠书,我们只能从上面放或取. 队列是遵循先进先出(FIFO)规则的一种有序集合,比如排队,先排到的先离开. 数组也是一种有序的集合,它与上面 ...

  10. Phpstorm中使用SFTP

    Phpstorm中经常会出现FTP连接失败的问题,这个时候我们可以使用SFTP来连接服务器. 1.添加服务器.tools--deployment--configuration/browse Remot ...