到目前为止,咱们已经写了三个模块的开发了。咱们已经抽取过了BaseAction、BaseDao,咱们此次来看看咱们的Service接口。php
/** * 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); }
/** * 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() ; }
/** * 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
在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(); }
咱们的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(); } }
InfoService继承了BaseService接口,因而就有了增删改查的方法。同时把泛型T的类型肯定下来。markdown
/** * created by ozc on 2017/5/23. */ public interface InfoService extends BaseService<Info> { }
继承了InfoService,有了增删该查的方法,然而具体的操做是BaseServiceImpl中实现的。咱们继承它,并给出泛型T对应的类型。ide
@Service public class InfoServiceImpl extends BaseServiceImpl<Info> implements InfoService { }
如今的问题是什么呢???咱们在BaseServiceImpl中使用了BaseDao这个变量来对数据库进行操做。但是在BaseServiceImpl中是没有BaseDao这个变量的。工具
首先,要明确的是,咱们不能在BaseServiceImpl中注入BaseDao,由于BaseServiceImpl自己就是一个抽象类。那咱们怎么对BaseDao进行实例化呢???优化
咱们能够这样作:this
最后,咱们在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; } }
//经过BaseDao来操做数据库 private BaseDao<T> baseDao; public void setBaseDao(BaseDao<T> baseDao) { this.baseDao = baseDao; }
咱们来实现下面的功能:
其实也是一个查询,只不过查询多了一个条件罢了。按照传统的方式咱们能够这样作:
//根据条件查询列表 List<T> findObjects(String sql, List<Object> objectList);
@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(); }
//根据条件查询列表 List<T> findObjects(String sql, List<Object> objectList);
@Override public List<T> findObjects(String sql, List<Object> objectList) { return baseDao.findObjects(sql, objectList); }
咱们仍是用着listUI这个方法,由于它仅仅是参数可能不一样。
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; } }
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"; }