多条件分页查询,省掉麻烦的空值判断
在之前做的一个基于java的web项目中,有很多多条件查询,每个条件都需要判断下是不是空,然后再拼起来,做组合查询,觉得很烦,就想能不能自己封装一套高层的api,自动忽略空值的条件,自动实现统计总数,自动翻页,等功能;后来又加上了条件优先级,如果某个字段不是空,则其他某个字段不参与查询(就是条件优先级,比如如果条件2不是空,则条件1不生效),这样我就自己写了一个符合这个要求的实现。我觉得这个东西有价值,跟大家分享一下。
访问数据库我用的hibernate,我的这套api跟hibernate的critical查询比较像,不过我是基于hql拼条件的思路做的,下面看例子:
原来多条件查询的例子:
1 @Override
2 @Transactional(readOnly = true, rollbackFor = Exception.class )
3 public Page<Dictionary> findByPage(int pageNo, String table, String name,Dictionary pareDict) {
4 Page<Dictionary> page = new Page<Dictionary>();
5 page.setAutoCount(true);
6 page.setPageNo(pageNo);
7 page.setPageSize(5);
8
9 if(name==null || name.equals("")){//判断输入条件的空值
10 if(pareDict!=null){
11 Query query = getQueryForFind(pareDict.getId(), table);
12 int count = query.list().size();
13 List<Dictionary> list = query.setMaxResults(5).setFirstResult((pageNo - 1) * 5).list();
14 page.setRows(list);
15 page.setTotal(count);
16 return page;
17 }else{
18 return dictionaryDao.findByCriteria(page,Restrictions.eq("tableName", table));
19 }
20
21 }else{
22 if(pareDict!=null){//判断输入条件空值
23return dictionaryDao.findByCriteria(page,Restrictions.eq("tableName", table),
24 Restrictions.like("name", "%"+name+"%"),Restrictions.eq("parentTable", pareDict));
25 }else{
26 return dictionaryDao.findByCriteria(page,Restrictions.eq("tableName", table),
27 Restrictions.like("name", "%"+name+"%"));
28 }
29 }
30
31 }
这个例子逻辑看不懂没有关系,只要能看出来原来是怎么根据多个条件进行判断的就好了,相信很多做过java的人都会有这方面的经验。
以下是使用我写的api查询的例子:
private List<Well> find(Integer jobid, String state, List<String> wellNames) throws Exception {
Page<WellJob> page = new Page<WellJob>();//初始化一个分页查询结果对象,用于接收查询结果
page.setPageSize(rows.size());//设置一页大小
PageQuery<WellJob> query = new PageQuery<WellJob>(page);//用page对象构造查询对象
query.setCount(false);//设定是否自动获取总数,如果获取的话,只会统计一次
query.addTable(WellJob.class, null);//addtable可以多次调用,用于联合查询,第二个参数是表别名,null的话表示用默认值
query.addConditon("jobType.id", OP.eq, jobid).and("state", OP.eq, state).and("well.wellNum", OP.in, wellNames);
//addCondition 这个方法表示设置条件的开始,只能调用一次,如果第三个参数是null,则忽略这次方法调用
//add 与条件,如果第三个参数是null,忽略这次方法调用
//query 对象上基本每个api的返回值都是自身,api可以连续调用,编码更流畅
this.pageQueryService.getNextPage(query);//获取下一页,如果page参数从页面上传回来,这个方法就是翻页了
//this.pageQueryService 对象是全局对象,基本上就是个壳,不用关心,主要功能都是在query对象里边实现的
//以下代码都是分析结果的,于查询api关系不大
Set<Long> wellNumSet = new HashSet<Long>();
for (WellJob wj : page.getRows()) {
wellNumSet.add(wj.getWell().getId());
}
List<Well> result = new ArrayList<Well>(rows.size() - wellNumSet.size());
for (Well w : rows) {
if (!wellNumSet.contains(w.getId())) {
result.add(w);
}
}
return result;
}
查询对象的主要api:
package com.secneo.common; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import org.apache.commons.lang.xwork.StringUtils; import org.hibernate.Query; import org.hibernate.classic.Session; import org.secneo.framework.orm.hibernate.Page; /** * 分页查询 工具, 原理类似hibernate 的critical工具,但用法上不同, 可以与pageQueryService 配合,在 action中直接使用, * 本质上该工具是对hql的封装, 封装后 * 目的是提供简易的分页查询接口,可以设定为自动计算总条目数。 * 可以设定条件的替换规则,如 第二个条件不为空时 ,第一个条件则不生效, * * @author ZDCIN * */ public class PageQuery<T> { private Page<T> page; // private List<String> tables = new ArrayList<String>(); private String where = ""; private Map<Integer, CondTuple> conditionMap = new HashMap<Integer, CondTuple>(); private String orderBy = ""; private int conditionIndex = 0; private boolean isCount = true; /** * 查看是否计算总数, 默认true, 计算总数的条件是 isCount = true * @return */ public boolean isCount() { return isCount; } /** * 设置是否计算总数, 默认true * @return */ public void setCount(boolean isCount) { this.isCount = isCount; } /** * 设定page对象,和返回类型T * @param page */ public PageQuery(Page<T> page) { this.page = page; } private String selectSql = ""; /** * 当获取字段不是一个标准bean或者不是一个bean的全部字段的时候使用, 默认不用调用该方法 * @param selectSql * @return */ public PageQuery<T> setSelectSql(String selectSql) { this.selectSql = selectSql; return this; } private String countSql; /** * 当count语句不能从select简易变化过来的时候使用。 比如有distinct限制的时候 * @param countSql * @return */ public PageQuery<T> setCountSql(String countSql) { this.countSql = countSql; return this; } private String fromSql; /** * 添加要查询的表,并设定别名, 该方法可以多次调用,作为多表联合查询。 * @param tableClass * @param alias 可以为空,表示没有别名 * @return */ @SuppressWarnings("rawtypes") public PageQuery<T> addTable(Class tableClass, String alias) { 。。。。。 } /** * 添加条件, 该方法只能调用一次,且必须在and 或者or之前调用 * @param filedName 字段名, 别名和字段的组合形式, * @param op 字段上的条件操作, 如等于, 大于, in like等, * @param value 如果value为空,则该条件不生效, 但当op是 innotnull或者isnull的时候例外,该条件会生效 * @return */ public PageQuery<T> addConditon(String filedName, OP op, Object value) { 。。。。 } /** * addConditon(String filedName, OP op, Object value) 的简写形式, op 是eq * @param filedName * @param value * @return */ public PageQuery<T> addConditon(String filedName, Object value) { return this.addConditon(filedName, OP.eq, value); } private static enum LogicOp { and, or; } private PageQuery<T> and_AND_or(LogicOp logicOP, String filedName, OP op, Object value, String replaceWhich) { 。。。。 } /** * 添加and条件, where中的条件都是平级的,如果有括号,则用逻辑运算规则拉平 * * @param filedName 与addConditon中意义相同 * @param op 与addConditon中意义相同 * @param value 与addConditon中意义相同 * @param replaceWhich 替换列表, 如果该方法中value不为空,则替换列表中的字段,如“1,2” * * @return */ public PageQuery<T> and(String filedName, OP op, Object value, String replaceWhich) { return this.and_AND_or(LogicOp.and, filedName, op, value, replaceWhich); } /** * and(String filedName, OP op, Object value, String replaceWhich) 的简写形式 * @param filedName * @param op * @param value * @return */ public PageQuery<T> and(String filedName, OP op, Object value) { return this.and_AND_or(LogicOp.and, filedName, op, value, null); } /** * and(String filedName, OP op, Object value, String replaceWhich) 的简写形式 * @param filedName * @param value * @return */ public PageQuery<T> and(String filedName, Object value) { return this.and_AND_or(LogicOp.and, filedName, OP.eq, value, null); } /** * 添加or条件, where中的条件都是平级的,如果有括号,则用逻辑运算规则拉平 * * @param filedName 与addConditon中意义相同 * @param op 与addConditon中意义相同 * @param value 与addConditon中意义相同 * @param replaceWhich 替换列表, 如果该方法中value不为空,则替换列表中的字段,如“1,2” * * @return */ public PageQuery<T> or(String filedName, OP op, Object value, String replaceWhich) { return this.and_AND_or(LogicOp.or, filedName, op, value, replaceWhich); } /** * 同 or(String filedName, OP op, Object value, String replaceWhich) * @param filedName * @param op * @param value * @return */ public PageQuery<T> or(String filedName, OP op, Object value) { return this.and_AND_or(LogicOp.or, filedName, op, value, null); } /** * 同 or(String filedName, OP op, Object value, String replaceWhich) * @param filedName * @param value * @return */ public PageQuery<T> or(String filedName, Object value) { return this.and_AND_or(LogicOp.or, filedName, OP.eq, value, null); } /** * 添加排序, 可调用多次 * @param filedName 与addConditon中意义相同 * @param orderType OrderType.ASC, OrderType.DESC * @return */ public PageQuery<T> addOrderBy(String filedName, OrderType orderType) { 。。。。 } /** * 执行查询, 在pageQueryService中调用, service可以提供hibernate session对象 * @param currentSession * @return */ public Page<T> excuteQuery(Session currentSession) { 。。。。 } }
page对象api:
public class Page<T> {public Page() { } public Page(Integer pageSize, boolean autoCount) { } /** * 每页的记录数量,默认值 15. */ public Integer getPageSize() { } public boolean isPageSizeSetted() { } public void setPageSize(Integer pageSize) { } /** * 当前页的页号,序号从1开始. */ public Integer getPageNo() { } public void setPageNo(Integer pageNo) { } /** * 第一条记录在结果集中的位置,序号从0开始. */ public Integer getFirst() { } public boolean isFirstSetted() { } public boolean isOrderBySetted() { } /** * 是否自动获取总页数,默认为false,query by HQL时本属性无效. */ public boolean isAutoCount() { } public void setAutoCount(boolean autoCount) { } /** * 页内的数据列表. */ public List<T> getRows() { } public void setRows(List<T> result) { } /** * 总记录数. */ public Integer getTotal() { } public void setTotal(Integer totalCount) { } /** * 计算总页数. */ public Integer getTotalPages() { } /** * 是否还有下一页. */ public boolean isHasNext() { } /** * 返回下页的页号,序号从1开始. */ public Integer getNextPage() { } /** * 是否还有上一页. */ public boolean isHasPre() { } /** * 返回上页的页号,序号从1开始. */ public Integer getPrePage() { } /** * 得到分页条件仅支持like查询 */ public Map<String, Object> getCondition() { } public void setCondition(Map<String, Object> condition) { } /** * 多排序条件 * * @return */ public String[][] getOrderByArr() { } public void setOrderByArr(String[][] orderByArr) { } public String getMemo() { } public void setMemo(String memo) { } }
page对象功能比较直观,但因为大部分代码都不是我写的,page的源码我就不提供了。
这个api就是为了解决多个条件任意组合的联合查询的问题,省去if判断空值,省去写额外的统计总数代码,还提供条件优先级的功能。
我的这个代码不会那么容易跑起来,我觉得比代码更重要的是,提供一种简化问题、解决问题的思路。如果读者您对这个问题跟我一样感兴趣,欢迎讨论。
以下是query对象和queryService对象的的全部源码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.math.BigDecimal; 2 import java.math.BigInteger; 3 import java.util.ArrayList; 4 import java.util.Date; 5 import java.util.HashMap; 6 import java.util.List; 7 import java.util.Locale; 8 import java.util.Map; 9 10 import org.apache.commons.lang.xwork.StringUtils; 11 import org.hibernate.Query; 12 import org.hibernate.classic.Session; 13 import org.secneo.framework.orm.hibernate.Page; 14 15 /** 16 * 分页查询 工具, 原理类似hibernate 的critical工具,但用法上不同, 可以与pageQueryService 配合,在 action中直接使用, 17 * 本质上该工具是对hql的封装, 封装后 18 * 目的是提供简易的分页查询接口,可以设定为自动计算总条目数。 19 * 可以设定条件的替换规则,如 第二个条件不为空时 ,第一个条件则不生效, 20 * 21 * @author ZDCIN 22 * 23 */ 24 public class PageQuery<T> { 25 26 private Page<T> page; 27 // private List<String> tables = new ArrayList<String>(); 28 private String where = ""; 29 private Map<Integer, CondTuple> conditionMap = new HashMap<Integer, CondTuple>(); 30 private String orderBy = ""; 31 32 private int conditionIndex = 0; 33 private boolean isCount = true; 34 35 /** 36 * 查看是否计算总数, 默认true, 计算总数的条件是 isCount = true 37 * @return 38 */ 39 public boolean isCount() { 40 return isCount; 41 } 42 /** 43 * 设置是否计算总数, 默认true 44 * @return 45 */ 46 public void setCount(boolean isCount) { 47 this.isCount = isCount; 48 } 49 /** 50 * 设定page对象,和返回类型T 51 * @param page 52 */ 53 public PageQuery(Page<T> page) { 54 this.page = page; 55 } 56 57 private String selectSql = ""; 58 59 /** 60 * 当获取字段不是一个标准bean或者不是一个bean的全部字段的时候使用, 默认不用调用该方法 61 * @param selectSql 62 * @return 63 */ 64 public PageQuery<T> setSelectSql(String selectSql) { 65 this.selectSql = selectSql; 66 return this; 67 } 68 private String countSql; 69 70 /** 71 * 当count语句不能从select简易变化过来的时候使用。 比如有distinct限制的时候 72 * @param countSql 73 * @return 74 */ 75 public PageQuery<T> setCountSql(String countSql) { 76 this.countSql = countSql; 77 return this; 78 } 79 80 private String fromSql; 81 82 /** 83 * 添加要查询的表,并设定别名, 该方法可以多次调用,作为多表联合查询。 84 * @param tableClass 85 * @param alias 可以为空,表示没有别名 86 * @return 87 */ 88 @SuppressWarnings("rawtypes") 89 public PageQuery<T> addTable(Class tableClass, String alias) { 90 if (StringUtils.isBlank(this.fromSql)) { 91 this.fromSql = " FROM "; 92 } else { 93 this.fromSql += ", "; 94 } 95 if (StringUtils.isNotBlank(alias)) { 96 this.fromSql += tableClass.getSimpleName() + " AS " + alias; 97 } else { 98 this.fromSql += tableClass.getSimpleName() + " "; 99 } 100 return this; 101 } 102 103 /** 104 * 添加条件, 该方法只能调用一次,且必须在and 或者or之前调用 105 * @param filedName 字段名, 别名和字段的组合形式, 106 * @param op 字段上的条件操作, 如等于, 大于, in like等, 107 * @param value 如果value为空,则该条件不生效, 但当op是 innotnull或者isnull的时候例外,该条件会生效 108 * @return 109 */ 110 public PageQuery<T> addConditon(String filedName, OP op, Object value) { 111 CondTuple tuple = new CondTuple(null, filedName, op, value, null); 112 this.conditionMap.put(this.conditionIndex ++, tuple); 113 return this; 114 // if (value == null) { 115 // return this; 116 // } 117 // //String filedFullName = this.filedName(tableIndex, filedName); 118 // this.condition = " WHERE " + filedName + op.v() + ":" + filedName; 119 // this.conditionMap.put(filedName, value); 120 // return this; 121 } 122 123 124 /** 125 * addConditon(String filedName, OP op, Object value) 的简写形式, op 是eq 126 * @param filedName 127 * @param value 128 * @return 129 */ 130 public PageQuery<T> addConditon(String filedName, Object value) { 131 return this.addConditon(filedName, OP.eq, value); 132 } 133 134 private static enum LogicOp { 135 and, or; 136 } 137 138 private PageQuery<T> and_AND_or(LogicOp logicOP, String filedName, OP op, Object value, 139 String replaceWhich) { 140 CondTuple tuple = new CondTuple(logicOP, filedName, op, value, replaceWhich); 141 this.conditionMap.put(this.conditionIndex ++, tuple); 142 return this; 143 // if (value == null) { 144 // return this; 145 // } 146 // if (StringUtils.isBlank(this.condition)) { 147 // this.condition = " WHERE "; 148 // } else { 149 // this.condition += " " + logicOP.name() + " "; 150 // } 151 // //String filedFullName = this.filedName(tableIndex, filedName); 152 // this.condition += filedName + op.v() + ":" + filedName; 153 // this.conditionMap.put(filedName, value); 154 // return this; 155 } 156 157 /** 158 * 添加and条件, where中的条件都是平级的,如果有括号,则用逻辑运算规则拉平 159 * 160 * @param filedName 与addConditon中意义相同 161 * @param op 与addConditon中意义相同 162 * @param value 与addConditon中意义相同 163 * @param replaceWhich 替换列表, 如果该方法中value不为空,则替换列表中的字段,如“1,2” 164 * 165 * @return 166 */ 167 public PageQuery<T> and(String filedName, OP op, Object value, String replaceWhich) { 168 return this.and_AND_or(LogicOp.and, filedName, op, value, replaceWhich); 169 } 170 171 /** 172 * and(String filedName, OP op, Object value, String replaceWhich) 的简写形式 173 * @param filedName 174 * @param op 175 * @param value 176 * @return 177 */ 178 public PageQuery<T> and(String filedName, OP op, Object value) { 179 return this.and_AND_or(LogicOp.and, filedName, op, value, null); 180 } 181 182 /** 183 * and(String filedName, OP op, Object value, String replaceWhich) 的简写形式 184 * @param filedName 185 * @param value 186 * @return 187 */ 188 public PageQuery<T> and(String filedName, Object value) { 189 return this.and_AND_or(LogicOp.and, filedName, OP.eq, value, null); 190 } 191 192 /** 193 * 添加or条件, where中的条件都是平级的,如果有括号,则用逻辑运算规则拉平 194 * 195 * @param filedName 与addConditon中意义相同 196 * @param op 与addConditon中意义相同 197 * @param value 与addConditon中意义相同 198 * @param replaceWhich 替换列表, 如果该方法中value不为空,则替换列表中的字段,如“1,2” 199 * 200 * @return 201 */ 202 public PageQuery<T> or(String filedName, OP op, Object value, String replaceWhich) { 203 return this.and_AND_or(LogicOp.or, filedName, op, value, replaceWhich); 204 } 205 206 207 /** 208 * 同 or(String filedName, OP op, Object value, String replaceWhich) 209 * @param filedName 210 * @param op 211 * @param value 212 * @return 213 */ 214 public PageQuery<T> or(String filedName, OP op, Object value) { 215 return this.and_AND_or(LogicOp.or, filedName, op, value, null); 216 } 217 218 /** 219 * 同 or(String filedName, OP op, Object value, String replaceWhich) 220 * @param filedName 221 * @param value 222 * @return 223 */ 224 public PageQuery<T> or(String filedName, Object value) { 225 return this.and_AND_or(LogicOp.or, filedName, OP.eq, value, null); 226 } 227 228 /** 229 * 添加排序, 可调用多次 230 * @param filedName 与addConditon中意义相同 231 * @param orderType OrderType.ASC, OrderType.DESC 232 * @return 233 */ 234 public PageQuery<T> addOrderBy(String filedName, OrderType orderType) { 235 if (StringUtils.isBlank(filedName)) { 236 return this; 237 } 238 if (StringUtils.isBlank(this.orderBy)) { 239 this.orderBy = " ORDER BY "; 240 } else { 241 this.orderBy += ","; 242 } 243 this.orderBy += filedName + " " + orderType.name(); 244 return this; 245 } 246 247 248 /** 249 * 执行查询, 在pageQueryService中调用, service可以提供hibernate session对象 250 * @param currentSession 251 * @return 252 */ 253 public Page<T> excuteQuery(Session currentSession) { 254 List<Integer> replaceList = this.getReplaceList(); 255 this.buildWhereStatementInSql(replaceList); 256 257 if (page.getTotal() == -1) { 258 String countHql = "SELECT " + (StringUtils.isBlank(this.countSql) ? " COUNT(*) " : this.countSql) 259 + this.fromSql + this.where; 260 261 Query hquery = currentSession.createQuery(countHql); 262 this.buildHibernateQuery(replaceList, hquery); 263 Long totalCol = (Long) hquery.uniqueResult(); 264 265 page.setTotal(totalCol.intValue()); 266 // page.setPageNo(1);//肯定是从第一页开始 267 } 268 String hql = this.selectSql + this.fromSql + this.where + this.orderBy; 269 System.out.println("query sql is:" + hql); 270 Query hquery = currentSession.createQuery(hql); 271 this.buildHibernateQuery(replaceList, hquery); 272 @SuppressWarnings("unchecked") 273 List<T> resultSet= hquery.setFirstResult(this.page.getFirst()).setMaxResults(this.page.getPageSize()).list(); 274 this.page.setRows(resultSet); 275 return this.page; 276 } 277 278 private void buildHibernateQuery(List<Integer> replaceList, Query hquery) { 279 for (int i = 0; i < this.conditionIndex; i++) { 280 CondTuple tuple = this.conditionMap.get(i); 281 if (replaceList.contains(i)) { 282 continue; 283 } 284 if (tuple.value != null && !tuple.op.equals(OP.in)) { 285 this.putObjectToHql(hquery, tuple.valueNameInHql + i, tuple.value); 286 } 287 } 288 } 289 290 private void putObjectToHql(Query hquery, String valueNameInHql, Object value) { 291 // valueNameInHql = valueNameInHql.replace('.', '_'); 292 //valueName 是hql中的冒号后边的单词,用于hql执行时用变量替换,里边不能含有下列字符 293 // String valueNameInHql = valueNameInHql; 294 valueNameInHql = valueNameInHql.replace('.', '_'); 295 valueNameInHql = valueNameInHql.replaceAll(" ", ""); 296 valueNameInHql = valueNameInHql.replaceAll("-", ""); 297 valueNameInHql = valueNameInHql.replaceAll("\\(", ""); 298 valueNameInHql = valueNameInHql.replaceAll("\\)", ""); 299 if (value instanceof Long) { 300 hquery.setLong(valueNameInHql, (Long) value); 301 } else if (value instanceof String) { 302 hquery.setString(valueNameInHql, (String) value); 303 } else if (value instanceof Date) { 304 hquery.setTimestamp(valueNameInHql, (Date) value); 305 } else if (value instanceof BigDecimal) { 306 hquery.setBigDecimal(valueNameInHql, (BigDecimal) value); 307 } else if (value instanceof Integer) { 308 hquery.setInteger(valueNameInHql, (Integer) value); 309 } else if (value instanceof Double) { 310 hquery.setDouble(valueNameInHql, (Double) value); 311 } else if (value instanceof Float) { 312 hquery.setFloat(valueNameInHql, (Float) value); 313 } else if (value instanceof Boolean) { 314 hquery.setBoolean(valueNameInHql, (Boolean) value); 315 } else if (value instanceof byte[]) { 316 hquery.setBinary(valueNameInHql, (byte[]) value); 317 } else if (value instanceof Locale) { 318 hquery.setLocale(valueNameInHql, (Locale) value); 319 } else if (value instanceof BigInteger) { 320 hquery.setBigInteger(valueNameInHql, (BigInteger) value); 321 } else { 322 throw new RuntimeException("不支持的value类型:" + value.getClass()); 323 } 324 // 下面这些不常用,且麻烦,不支持 325 // setText(String, String) 326 // setSerializable(String, Serializable) 327 // setDate(String, Date) 328 // setTime(String, Date) 329 // setCalendar(String, Calendar) 330 // setCalendarDate(String, Calendar) 331 // setCharacter(String, char) 332 // setByte(String, byte) 333 // setShort(String, short) 334 } 335 336 private void buildWhereStatementInSql(List<Integer> replaceList) { 337 for (int i = 0; i < this.conditionIndex; i++) { 338 CondTuple tuple = this.conditionMap.get(i); 339 if (replaceList.contains(i)) { 340 continue; 341 } 342 if (tuple.value != null) { 343 //in 查询特殊处理 344 if (tuple.op.equals(OP.in)) { 345 List value = (List)tuple.value; 346 String temp = ""; 347 if (value == null || value.size() == 0) { 348 break; 349 } 350 if (value.get(0) instanceof String) { 351 temp = "('"; 352 for (String subv : (List<String>)value) { 353 temp += subv + "','"; 354 } 355 temp += "')"; 356 temp = temp.replace(",')", "')"); 357 } else if (value.get(0) instanceof Long){ 358 temp = "("; 359 for (Long subv : (List<Long>)value) { 360 temp += subv.longValue() + ","; 361 } 362 temp += ")"; 363 temp = temp.replace(",)", ")"); 364 }else { 365 temp = "("; 366 for (Integer subv : (List<Integer>)value) { 367 temp += subv.intValue() + ","; 368 } 369 temp += ")"; 370 temp = temp.replace(",)", ")"); 371 } 372 this.where += (tuple.logicOp == null ? "" : tuple.logicOp.name()) + " " + tuple.valueNameInHql + tuple.op.v() 373 + temp + " "; 374 } else { 375 //valueName 是hql中的冒号后边的单词,用于hql执行时用变量替换,里边不能含有下列字符 376 String valueName = tuple.valueNameInHql + i; 377 valueName = valueName.replace('.', '_'); 378 valueName = valueName.replaceAll(" ", ""); 379 valueName = valueName.replaceAll("-", ""); 380 valueName = valueName.replaceAll("\\(", ""); 381 valueName = valueName.replaceAll("\\)", ""); 382 this.where += (tuple.logicOp == null ? "" : tuple.logicOp.name()) + " " + tuple.valueNameInHql 383 + tuple.op.v() + ":" + valueName + " "; 384 } 385 } else { 386 if (tuple.op.equals(OP.isNull) || tuple.op.equals(OP.isNotNull)) { 387 this.where += (tuple.logicOp == null ? "" : tuple.logicOp.name()) + " " + tuple.valueNameInHql 388 + tuple.op.v() + " "; 389 } 390 } 391 } 392 if (StringUtils.isNotBlank(this.where)) { 393 this.where = " WHERE " + this.where; 394 if (this.where.contains("WHERE and")) { 395 this.where.replace("WHERE and", "WHERE "); 396 } else if (this.where.contains("WHERE or")) { 397 this.where.replace("WHERE or", "WHERE "); 398 } 399 } 400 } 401 private List<Integer> getReplaceList() { 402 List<Integer> result = new ArrayList<Integer>(); 403 String replaceString = ""; 404 for (int i = 0; i < this.conditionIndex; i++) { 405 CondTuple tuple = this.conditionMap.get(i); 406 if (tuple.value != null && StringUtils.isNotBlank(tuple.replaceString)) { 407 replaceString += tuple.replaceString; 408 } 409 } 410 String[] temp = replaceString.split(","); 411 if (temp == null || temp.length == 0) { 412 return result; 413 } 414 for (String t : temp) { 415 if (StringUtils.isBlank(t)) { 416 continue; 417 } 418 if (!result.contains(t)) { 419 result.add(Integer.parseInt(t)); 420 } 421 } 422 return result; 423 } 424 425 426 427 /**条件组合对象*/ 428 private static class CondTuple { 429 CondTuple(LogicOp logicOp, String valueNameInHql, OP op, Object value, String replaceString) { 430 this.logicOp = logicOp; 431 this.valueNameInHql = valueNameInHql; 432 this.op = op; 433 this.value = value; 434 this.replaceString = replaceString; 435 } 436 437 LogicOp logicOp; 438 String valueNameInHql; 439 OP op; 440 Object value; 441 String replaceString; 442 } 443 public static enum OrderType { 444 ASC,DESC; 445 } 446 public static enum OP { 447 eq { 448 { 449 value = "="; 450 } 451 }, 452 neq { 453 { 454 value = "<>"; 455 } 456 }, 457 gt { 458 { 459 value = ">"; 460 } 461 }, 462 lt { 463 { 464 value = "<"; 465 } 466 }, 467 ge { 468 { 469 value = ">="; 470 } 471 }, 472 le { 473 { 474 value = "<="; 475 } 476 }, 477 like { 478 { 479 value = " like "; 480 } 481 }, 482 in { 483 { 484 value = " in "; 485 } 486 }, 487 isNotNull { 488 { 489 value = " is not null "; 490 } 491 }, 492 isNull { 493 { 494 value = " is null "; 495 } 496 }; 497 protected String value = null; 498 499 public String v() { 500 return value; 501 } 502 } 503 504 505 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 @Service("pageQueryService") 2 public class PageQueryService { 3 4 private SessionFactory sessionFactory; 5 6 @Resource(name = "sessionFactory") 7 public void setSessionFactory(SessionFactory sessionFactory) { 8 this.sessionFactory = sessionFactory; 9 } 10 11 public <T> Page<T> getNextPage(PageQuery<T> pageQuery) { 12 Page<T> result = pageQuery.excuteQuery(this.sessionFactory.getCurrentSession()); 13 return result; 14 } 15 }
原文地址:http://www.cnblogs.com/zdcin/p/3152668.html