納稅服務系統【抽取BaseService、條件查詢】

抽取BaseService

到目前爲止,咱們已經寫了三個模塊的開發了。咱們已經抽取過了BaseAction、BaseDao,咱們此次來看看咱們的Service接口。php

  • 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。java

抽取BaseService

在core模塊中添加service包,抽取BaseServicesql

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的類型肯定下來。markdown

/** * created by ozc on 2017/5/23. */
    public interface InfoService extends BaseService<Info> {

    }
  • InfoServiceImpl

繼承了InfoService,有了增刪該查的方法,然而具體的操做是BaseServiceImpl中實現的。咱們繼承它,並給出泛型T對應的類型。ide

@Service
public class InfoServiceImpl extends BaseServiceImpl<Info> implements InfoService {


}

如今的問題是什麼呢???咱們在BaseServiceImpl中使用了BaseDao這個變量來對數據庫進行操做。但是在BaseServiceImpl中是沒有BaseDao這個變量的。工具

首先,要明確的是,咱們不能在BaseServiceImpl中注入BaseDao,由於BaseServiceImpl自己就是一個抽象類。那咱們怎麼對BaseDao進行實例化呢???優化

咱們能夠這樣作:this

  • 在InfoServiceImpl自己就須要注入InfoDao,來對數據庫的操做。
  • 而咱們這一次不使用屬性輸入,使用set方法注入
  • 在注入的同時,在BaseServiceImpl中給BaseDao設置set方法
  • 那麼咱們在注入的時候,就能夠調用BaseDao的set方法,把咱們要注入的對象給過去。
  • 最後,咱們在BaseServiceImpl中就有了baseDao這個變量了。spa

  • 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參數的方法就好了。
相關文章
相關標籤/搜索