• 纳税服务系统【抽取BaseService、条件查询】


    抽取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参数的方法就行了。

  • 相关阅读:
    浅谈Charles —— 青花瓷
    jdbc
    装饰者模式
    java可变参数
    简单日历
    DVD管理系统
    图片拷贝
    时间输出
    java基础小知识
    jQuery HTML
  • 原文地址:https://www.cnblogs.com/zhong-fucheng/p/7202911.html
Copyright © 2020-2023  润新知