<!--前段时间看到hibernate的PropertyFilter工具类,感觉思想挺不错,项目中用的mybatis,所以 实现了一个mybatis版的PropertyFilter,仅限思想,代码运行可能有错,需要调试--> <select id="selectInfoPage" resultType="hashmap" parameterType="com.utils.MybatisPropertyFilter" > SELECT * FROM art_info art left join artist artist on art.artist_id = artist.id <include refid="SqlMapper.Example_Where_Clause_None_Order"/> </select>
<sql id="Example_Where_Clause_None_Order"> <where> <foreach collection="oredCriteria" item="criteria" separator="or"> <if test="criteria.valid"> <trim prefix="(" suffix=")" prefixOverrides="and"> <foreach collection="criteria.criteria" item="criterion"> <choose> <when test="criterion.noValue"> and ${criterion.condition} </when> <when test="criterion.singleValue"> and ${criterion.condition} #{criterion.value} </when> <when test="criterion.betweenValue"> and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} </when> <when test="criterion.listValue"> and ${criterion.condition} <foreach collection="criterion.value" item="listItem" open="(" close=")" separator=","> #{listItem} </foreach> </when> </choose> </foreach> </trim> </if> </foreach> </where> </sql>
/** *Mybatis 版 PropertyFilter */ import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.commons.beanutils.ConvertUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateFormatUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.Assert; /** * @author Administrator * */ public class MybatisPropertyFilter { private static final Logger logger = LoggerFactory.getLogger(MybatisPropertyFilter.class); protected String orderByClause; protected boolean distinct; protected List<Criteria> oredCriteria; public MybatisPropertyFilter(){ oredCriteria = new ArrayList<Criteria>(); } /** * 从HttpRequest中创建PropertyFilter列表 * PropertyFilter命名规则为Filter属性前缀_比较类型属性类型_属性名. * * eg. * filter_EQS_name * filter_LIKES_name_OR_email */ public static MybatisPropertyFilter buildFromHttpRequest(final HttpServletRequest request, final String filterPrefix) { MybatisPropertyFilter filter = new MybatisPropertyFilter(); Map<String, Object> filterParamMap = ServletUtils.getParametersStartingWith(request, filterPrefix + "_"); for(Map.Entry<String, Object> entry : filterParamMap.entrySet()) { String filterName = entry.getKey(); Object value = entry.getValue(); String firstPart = StringUtils.substringBefore(filterName, "_"); String matchTypeCode = StringUtils.substring(firstPart, 0, firstPart.length() - 1); String propertyTypeCode = StringUtils.substring(firstPart, firstPart.length() - 1, firstPart.length()); MatchType matchType = null; try { matchType = Enum.valueOf(MatchType.class, matchTypeCode); } catch(RuntimeException e) { throw new IllegalArgumentException("filter名称" + filterName + "没有按规则编写,无法得到属性比较类型.", e); } Class propertyClass = null; try { propertyClass = Enum.valueOf(PropertyType.class, propertyTypeCode).getValue(); } catch(RuntimeException e) { throw new IllegalArgumentException("filter名称" + filterName + "没有按规则编写,无法得到属性值类型.", e); }
if(value instanceof String[]) { filter.addCriterion(filterName, value, matchType); }else if(StringUtils.isNotBlank((String)value)) { filter.addCriterion(filterName, value, matchType); } } return filter; } /** * 向第一组查询条件增加条件 * @param propertyName 列名称 * @param propertyValue 列的值 * @param matchType 条件类型 */ public void addCriterion(final String propertyName, final Object propertyValue, final MatchType matchType) { addCriterion(propertyName, propertyValue, matchType, 0); } /** * @param propertyFilter * @param index 条件所在的组 */ public void addCriterion(final String propertyName, final Object propertyValue, final MatchType matchType, int index) { if(oredCriteria.size() == 0 || oredCriteria.size()<index || null == oredCriteria.get(index)){ oredCriteria.add(index, createCriteriaInternal()); } String[] propertyNameStr = StringUtils.splitByWholeSeparator(propertyName, PropertyFilter.OR_SEPARATOR); if(propertyNameStr.length>1) { Criterion criterion = buildCriterion(propertyName, propertyValue, matchType); oredCriteria.get(index).getCriteria().add(criterion); } else {//如果是OR条件 StringBuffer sb = new StringBuffer(); for(String param : propertyNameStr) { Criterion criterion = buildCriterion(param, propertyValue, matchType); sb.append(" or ").append(criterionToString(criterion)).append(" "); } if(sb.length() > 0) { Criterion criterion = new Criterion(sb.delete(0, 4).insert(0, "( ").append(") ").toString()); oredCriteria.get(index).getCriteria().add(criterion); } } } public enum LikeType { /** 左边% */ LL, /** 右边% */ RL; } protected Criterion buildCriterion(final String propertyName, final Object propertyValue, final MatchType matchType) { Assert.hasText(propertyName, "属性名称为空"); Criterion criterion = null; switch(matchType) { case EQ: if(propertyValue instanceof List<?>) { criterion = new Criterion(propertyName + " in ", propertyValue); }else if(propertyValue instanceof Object[]) { criterion = new Criterion(propertyName + " in ", propertyValue); }else { criterion = new Criterion(propertyName + " = ", propertyValue); } break; case NE: if(propertyValue instanceof List<?>) { criterion = new Criterion(propertyName + " not in ", propertyValue); } else { criterion = new Criterion(propertyName + " != ", propertyValue); } break; case LIKE: String likePart = StringUtils.substringBefore(propertyName, "_"); try { LikeType likeType = LikeType.valueOf(likePart); switch(likeType) { case LL: criterion = new Criterion(propertyName + " LIKE '%" + propertyValue + "' "); break; case RL: criterion = new Criterion(propertyName + " LIKE '" + propertyValue + "%' "); break; default: criterion = new Criterion(propertyName + " LIKE '%" + propertyValue + "%'"); break; } } catch(Exception e) { logger.debug("{}", e); criterion = new Criterion(propertyName + " LIKE '%" + propertyValue + "%'"); } break; case LE: criterion = new Criterion(propertyName + " <= ", propertyValue); break; case LT: criterion = new Criterion(propertyName + " < ", propertyValue); break; case GE: criterion = new Criterion(propertyName + " >= ", propertyValue); break; case GT: criterion = new Criterion(propertyName + " > ", propertyValue); } return criterion; } protected String criterionToString(final Criterion criterion) { if(criterion == null) return ""; StringBuffer sb = new StringBuffer(); if(criterion.isNoValue()) { sb.append(" ").append(criterion.getCondition()).append(" "); } else if(criterion.isSingleValue()) { sb.append(" ").append(criterion.getCondition()).append(convert(criterion.getValue())).append(" "); } else if(criterion.isListValue()) { StringBuffer values = new StringBuffer(); if(criterion.getValue() instanceof List<?>) { for(Object obj : (List<?>)criterion.getValue()) { values.append(convert(obj)).append(", "); } if(values.length() > 0) { values.delete(values.length() - 2, values.length()).insert(0, "(").append(")"); } sb.append(" ").append(criterion.getCondition()).append(values).append(" "); } else { sb.append(" ").append(criterion.getCondition()).append(convert(criterion.getValue())).append(" "); } } else if(criterion.isBetweenValue()) { sb.append(" ").append(criterion.getCondition()).append(convert(criterion.getValue())).append(" and ").append(convert(criterion.getSecondValue())).append(" "); } return sb.toString(); } protected static String convert(Object obj) { if(obj instanceof String){ return "'"+obj+"'"; }else if(obj instanceof Date){ return "'"+DateFormatUtils.format((Date)obj, "yyyy-MM-dd HH:mm:ss")+"'"; } return ConvertUtils.convert(obj); } public void setOrderByClause(String orderByClause) { this.orderByClause = orderByClause; } public String getOrderByClause() { return orderByClause; } public void setDistinct(boolean distinct) { this.distinct = distinct; } public boolean isDistinct() { return distinct; } public List<Criteria> getOredCriteria() { return oredCriteria; } public void or(Criteria criteria) { oredCriteria.add(criteria); } public Criteria or() { Criteria criteria = createCriteriaInternal(); oredCriteria.add(criteria); return criteria; } public Criteria createCriteria() { Criteria criteria = createCriteriaInternal(); if(oredCriteria.size() == 0) { oredCriteria.add(criteria); } return criteria; } protected Criteria createCriteriaInternal() { Criteria criteria = new Criteria(); return criteria; } public void clear() { oredCriteria.clear(); orderByClause = null; distinct = false; } /** * 属性比较类型枚举<p> * * @author */ public enum MatchType { /** 等于 */ EQ, /** 不等于 */ NE, /** 小于 */ LT, /** 大于 */ GT, /** 小于等于 */ LE, /** 大于等于 */ GE, /** 模糊匹配 */ LIKE; } /** * 属性数据类型枚举<p> * * @author */ public enum PropertyType { /** String */ S(String.class), /** Integer */ I(Integer.class), /** Long */ L(Long.class), /** Double */ N(Double.class), /** Date */ D(Date.class), /** Boolean */ B(Boolean.class); private Class<?> clazz; private PropertyType(Class<?> clazz) { this.clazz = clazz; } public Class<?> getValue() { return this.clazz; } } }
使用mybatis时参照hibernate的propertyFilter工具类实现,代码还有待改进