完整代码附件内
SpringSide PropertyFilter 的缺点:
1,不能A or B or C
2, 不能( A or B) and c
3, 不能包含between
4,不能属性间比较 field2 >field2
5,很难看的下划线 EQS_compId EQS_userName GES_recTime
6,即使已经知道具体类型,但也要转换成字符串
if (recForm.getBeginTime() != null && recForm.getEndTime() != null) { filters.add(new PropertyFilter("GES_recTime", DateFormatUtils .format(recForm.getBeginTime(), "HH:mm:ss"))); filters.add(new PropertyFilter("LES_recTime", DateFormatUtils .format(recForm.getEndTime(), "HH:mm:ss"))); }
7,功能有限的like
增强后的PropertyFilter
package com.sun4love.common.orm; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import org.apache.commons.beanutils.ConvertUtils; import org.springframework.util.Assert; /** * 属性过滤器 * * @author sun4love */ public class PropertyFilter { private String fieldName; private String otherField; private MatchType matchType; private boolean or; private boolean and; private boolean roundOr; private boolean roundAnd; private Object[] values; private List<PropertyFilter> filters = new ArrayList<PropertyFilter>(); /** * values为具体类型值的构造函数 * * @param fieldName * 属性名 * @param matchType * 匹配类型 {@link MatchType} * @param values * 值数组,MatchType为BETWEEN类型时,长度必须是2,其他为1,值必须是具体类型的值, * 如果是字符串需要转换类型,见另一个构造函数 * {@link #PropertyFilter(String, MatchType, FieldType, Object...)} */ public PropertyFilter(final String fieldName, MatchType matchType, Object... values) { this.fieldName = fieldName; this.matchType = matchType; if (this.matchType == MatchType.BETWEEN && (values == null || values.length != 2)) { throw new IllegalArgumentException(String.format( "%s属性选择MatchType.BETWEEN类型时,values参数长度必须为2", fieldName)); } this.values = values; filters.add(this); } /** * * values值需要转换类型的构造函数 * * @param fieldName * 属性名 * @param matchType * 匹配类型 {@link MatchType} * @param fieldType * 属性的类型,value将被转换到此类型 * @param values * 值数组,BETWEEN类型时,长度必须是2,其他为1,值必须是具体类型的值, 如果是字符串需要转换类型,见另一个构造函数 * {@link #FieldFilter(String, MatchType, FieldType, Object...)} */ public PropertyFilter(final String fieldName, MatchType matchType, FieldType fieldType, Object... values) { this.fieldName = fieldName; this.matchType = matchType; Assert.notEmpty(values); if (this.matchType == MatchType.BETWEEN && (values == null || values.length != 2)) { throw new IllegalArgumentException(String.format( "%s属性选择MatchType.BETWEEN类型时,values参数长度必须为2", fieldName)); } for (int i = 0; i < values.length; i++) { this.values[i] = ConvertUtils.convert(values[i], fieldType.getValue()); } filters.add(this); } /** * 属性比较构造函数 * * @param fieldName * 属性名 * @param matchType * 条件类型 * @param otherField * 其他属性 */ public PropertyFilter(final String fieldName, String otherField, MatchType matchType) { this.fieldName = fieldName; this.matchType = matchType; this.otherField = otherField; filters.add(this); } /** * 获取属性名 * * @return */ public String getFieldName() { return fieldName; } /** * 向当前filter添加一个or联合过滤条件 * * @param filter * @return */ public PropertyFilter addOrFilter(PropertyFilter filter) { filter.or = true; filters.add(filter); return this; } /** * 向当前filter添加一个or联合过滤条件, * <p> * 过滤条件将作为一个整体,即将所有条件放入括号内 * * @param filter * @return */ public PropertyFilter addRoundOrFilter(PropertyFilter filter) { Assert.isTrue(filter == this, "PropertyFilter不允许添加自身"); filter.roundOr = true; filters.add(filter); return this; } /** * 向当前filter添加一个and联合过滤条件, * * @param filter * @return */ public PropertyFilter addAndFilter(PropertyFilter filter) { Assert.isTrue(filter == this, "PropertyFilter不允许添加自身"); filter.and = true; filters.add(filter); return this; } /** * * 向当前filter添加一个and联合过滤条件, * <p> * 过滤条件将作为一个整体,即将所有条件放入括号内 * * @param filter * @return */ public PropertyFilter addRoundAndFilter(PropertyFilter filter) { Assert.isTrue(filter == this, "PropertyFilter不允许添加自身"); filter.roundAnd = true; filters.add(filter); return this; } /** * 判断该filter是否是一个or联合过滤,见{@link #addOrFilter(PropertyFilter)} * * @return */ public boolean isOr() { return or; } /** * 判断该filter是否是一个and联合过滤,见{@link #addAndFilter(PropertyFilter)} * * @return */ public boolean isAnd() { return and; } /** * 判断该filter是否是一个or联合过滤, 见 {@link #addRoundOrFilter(PropertyFilter)} * * @return */ public boolean isRoundOr() { return roundOr; } /** * 判断该filter是否是一个and联合过滤, 见 {@link #addRoundAndFilter(PropertyFilter)} * * @return */ public boolean isRoundAnd() { return roundAnd; } /** * 判断该filter是否是一个联合过滤 * @return */ public boolean isMulti() { return !filters.isEmpty(); } /** * 获取属性的比较类型 * @return */ public MatchType getMatchType() { return matchType; } /** * 获取属性比较参数值集合 * @return */ public Object[] getValues() { return values; } /** * 联合filter迭代器 * <p> * 不支持删除操作 * * @return */ public Iterator<PropertyFilter> iterator() { return new Iterator<PropertyFilter>() { private Iterator<PropertyFilter> it = filters.iterator(); public boolean hasNext() { return it.hasNext(); } public PropertyFilter next() { return it.next(); } public void remove() { throw new UnsupportedOperationException(); } }; } /** * 联合filter作为一个过滤条件 * * @param filter * @return */ public PropertyFilter joinFilter(PropertyFilter filter) { Assert.isTrue(filter == this, "PropertyFilter不允许添加自身"); filters.add(filter); return this; } /** * 其他field,两个属性比较时 * * @return */ public String getOtherField() { return otherField; } /** * 属性类型 * @author sun4love * */ public enum FieldType { String(String.class), Date(Date.class), Integer(Integer.class), Double( Double.class), Long(Long.class), Boolean(Boolean.class); private Class<?> clazz; private FieldType(Class<?> clazz) { this.clazz = clazz; } public Class<?> getValue() { return clazz; } } /** 属性比较类型. */ public enum MatchType { /** * 等于 * */ EQ, /** * 等于另一属性 * */ EQF, /** * like 'value' * */ LIKE, /** * like '%value' * */ LIKE_START, /** * like 'value%' * */ LIKE_END, /** * like '%value%' * */ LIKE_ANYWHERE, /** * 小于 * */ LT, /** * 小于另一属性 * */ LTF, /** * 大于 * */ GT, /** * 大于另一属性 * */ GTF, /** * 小于等于 * */ LE, /** * 小于等于另一属性 * */ LEF, /** * 大于等于 */ GE, /** * 大于等于另一属性 */ GEF, /** * * 在两者之间 * */ BETWEEN, /** * * 不等于 * */ NE, /** * * 不等于另一属性 * */ NEF } }
当然HibernateDao也需要修改
package com.sun4love.common.orm.hibernate; import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.SessionFactory; import org.hibernate.criterion.CriteriaSpecification; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.MatchMode; import org.hibernate.criterion.Order; import org.hibernate.criterion.Projection; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; import org.hibernate.impl.CriteriaImpl; import org.hibernate.transform.ResultTransformer; import org.springframework.util.Assert; import com.sun4love.common.reflection.ReflectionUtils; import com.sun4love.common.orm.Page; import com.sun4love.common.orm.PropertyFilter; import com.sun4love.common.orm.PropertyFilter.MatchType; /** * 封装SpringSide扩展功能的Hibernat DAO泛型基类. * * 扩展功能包括分页查询,按属性过滤条件列表查询. 可在Service层直接使用,也可以扩展泛型DAO子类使用,见两个构造函数的注释. * * @param <T> * DAO操作的对象类型 * @param <PK> * 主键类型 * * @author calvin */ public class HibernateDao<T, PK extends Serializable> extends SimpleHibernateDao<T, PK> { /** * 用于Dao层子类使用的构造函数. 通过子类的泛型定义取得对象类型Class. eg. public class UserDao extends * HibernateDao<User, Long>{ } */ public HibernateDao() { super(); } /** * 用于省略Dao层, Service层直接使用通用HibernateDao的构造函数. 在构造函数中定义对象类型Class. eg. * HibernateDao<User, Long> userDao = new HibernateDao<User, * Long>(sessionFactory, User.class); */ public HibernateDao(final SessionFactory sessionFactory, final Class<T> entityClass) { super(sessionFactory, entityClass); } // -- 分页查询函数 --// /** * 分页获取全部对象. */ public Page<T> getAll(final Page<T> page) { return findPage(page); } /** * 按HQL分页查询. * * @param page * 分页参数.不支持其中的orderBy参数. * @param hql * hql语句. * @param values * 数量可变的查询参数,按顺序绑定. * * @return 分页查询结果, 附带结果列表及所有查询时的参数. */ @SuppressWarnings({ "unchecked", "rawtypes" }) public Page<T> findPage(final Page<T> page, final String hql, final Object... values) { Assert.notNull(page, "page不能为空"); Query q = createQuery(hql, values); if (page.isAutoCount()) { long totalCount = countHqlResult(hql, values); page.setTotalCount(totalCount); } setPageParameter(q, page); List result = q.list(); page.setResult(result); return page; } /** * 按HQL分页查询. * * @param page * 分页参数. * @param hql * hql语句. * @param values * 命名参数,按名称绑定. * * @return 分页查询结果, 附带结果列表及所有查询时的参数. */ @SuppressWarnings({ "unchecked", "rawtypes" }) public Page<T> findPage(final Page<T> page, final String hql, final Map<String, ?> values) { Assert.notNull(page, "page不能为空"); Query q = createQuery(hql, values); if (page.isAutoCount()) { long totalCount = countHqlResult(hql, values); page.setTotalCount(totalCount); } setPageParameter(q, page); List result = q.list(); page.setResult(result); return page; } /** * 按Criteria分页查询. * * @param page * 分页参数. * @param criterions * 数量可变的Criterion. * * @return 分页查询结果.附带结果列表及所有查询时的参数. */ @SuppressWarnings({ "unchecked", "rawtypes" }) public Page<T> findPage(final Page<T> page, final Criterion... criterions) { Assert.notNull(page, "page不能为空"); Criteria c = createCriteria(criterions); if (page.isAutoCount()) { int totalCount = countCriteriaResult(c); page.setTotalCount(totalCount); } setPageParameter(c, page); List result = c.list(); page.setResult(result); return page; } /** * 设置分页参数到Query对象,辅助函数. */ protected Query setPageParameter(final Query q, final Page<T> page) { // hibernate的firstResult的序号从0开始 q.setFirstResult(page.getFirst() - 1); q.setMaxResults(page.getPageSize()); return q; } /** * 设置分页参数到Criteria对象,辅助函数. */ protected Criteria setPageParameter(final Criteria c, final Page<T> page) { // hibernate的firstResult的序号从0开始 c.setFirstResult(page.getFirst() - 1); c.setMaxResults(page.getPageSize()); if (page.isOrderBySetted()) { String[] orderByArray = StringUtils.split(page.getOrderBy(), ','); String[] orderArray = StringUtils.split(page.getOrder(), ','); Assert.isTrue(orderByArray.length == orderArray.length, "分页多重排序参数中,排序字段与排序方向的个数不相等"); for (int i = 0; i < orderByArray.length; i++) { if (Page.ASC.equals(orderArray[i])) { c.addOrder(Order.asc(orderByArray[i])); } else { c.addOrder(Order.desc(orderByArray[i])); } } } return c; } /** * 执行count查询获得本次Hql查询所能获得的对象总数. * * 本函数只能自动处理简单的hql语句,复杂的hql查询请另行编写count语句查询. */ protected long countHqlResult(final String hql, final Object... values) { String fromHql = hql; // select子句与order by子句会影响count查询,进行简单的排除. fromHql = "from " + StringUtils.substringAfter(fromHql, "from"); fromHql = StringUtils.substringBefore(fromHql, "order by"); String countHql = "select count(*) " + fromHql; try { Long count = findUnique(countHql, values); return count; } catch (Exception e) { throw new RuntimeException("hql can't be auto count, hql is:" + countHql, e); } } /** * 执行count查询获得本次Hql查询所能获得的对象总数. * * 本函数只能自动处理简单的hql语句,复杂的hql查询请另行编写count语句查询. */ protected long countHqlResult(final String hql, final Map<String, ?> values) { String fromHql = hql; // select子句与order by子句会影响count查询,进行简单的排除. fromHql = "from " + StringUtils.substringAfter(fromHql, "from"); fromHql = StringUtils.substringBefore(fromHql, "order by"); String countHql = "select count(*) " + fromHql; try { Long count = findUnique(countHql, values); return count; } catch (Exception e) { throw new RuntimeException("hql can't be auto count, hql is:" + countHql, e); } } /** * 执行count查询获得本次Criteria查询所能获得的对象总数. */ @SuppressWarnings({ "unchecked", "rawtypes" }) protected int countCriteriaResult(final Criteria c) { CriteriaImpl impl = (CriteriaImpl) c; // 先把Projection、ResultTransformer、OrderBy取出来,清空三者后再执行Count操作 Projection projection = impl.getProjection(); ResultTransformer transformer = impl.getResultTransformer(); List<CriteriaImpl.OrderEntry> orderEntries = null; try { orderEntries = (List) ReflectionUtils.getFieldValue(impl, "orderEntries"); ReflectionUtils .setFieldValue(impl, "orderEntries", new ArrayList()); } catch (Exception e) { logger.error("不可能抛出的异常:{}", e.getMessage()); } // 执行Count查询 int totalCount = ((Long) c.setProjection(Projections.rowCount()) .uniqueResult()).intValue(); // 将之前的Projection,ResultTransformer和OrderBy条件重新设回去 c.setProjection(projection); if (projection == null) { c.setResultTransformer(CriteriaSpecification.ROOT_ENTITY); } if (transformer != null) { c.setResultTransformer(transformer); } try { ReflectionUtils.setFieldValue(impl, "orderEntries", orderEntries); } catch (Exception e) { logger.error("不可能抛出的异常:{}", e.getMessage()); } return totalCount; } // -- 属性过滤条件(FieldFilter)查询函数 --// /** * 按属性查找对象列表,支持多种匹配方式. * * @param matchType * 匹配方式,目前支持的取值见FieldFilter的MatcheType enum. */ public List<T> findBy(final String fieldName, final Object value, final MatchType matchType) { Criterion criterion = buildFieldFilterCriterion(fieldName, new Object[] { value }, null, matchType); return find(criterion); } /** * 按属性过滤条件列表查找对象列表. */ public List<T> find(List<PropertyFilter> filters) { Criterion[] criterions = buildFieldFilterCriterions(filters); return find(criterions); } /** * 按属性过滤条件列表分页查找对象. */ public Page<T> findPage(final Page<T> page, final List<PropertyFilter> filters) { Criterion[] criterions = buildFieldFilterCriterions(filters); return findPage(page, criterions); } /** * 按属性条件列表创建Criterion数组,辅助函数. */ protected Criterion[] buildFieldFilterCriterions( final List<PropertyFilter> filters) { List<Criterion> criterionList = new ArrayList<Criterion>(); for (PropertyFilter filter : filters) { if (!filter.isMulti()) { criterionList.add(buildFieldFilterCriterion( filter.getFieldName(), filter.getValues(), filter.getOtherField(), filter.getMatchType())); } else { criterionList.add(buildMultiFieldFilter(filter)); } } return criterionList.toArray(new Criterion[criterionList.size()]); } protected Criterion buildMultiFieldFilter(PropertyFilter filter) { Criterion last = null; for (Iterator<PropertyFilter> it = filter.iterator(); it.hasNext();) { PropertyFilter ff = it.next(); Criterion c = buildFieldFilterCriterion(ff); if (ff.isAnd()) { last = new SimpleLogicalExpression(last, c, "and"); } else if (ff.isOr()) { last = new SimpleLogicalExpression(last, c, "or"); } else if (ff.isRoundAnd()) { last = Restrictions.and(last, c); } else if (ff.isRoundOr()) { last = Restrictions.or(last, c); } else { last = c; } } return last; } /** * 按属性条件参数创建Criterion,辅助函数. */ protected Criterion buildFieldFilterCriterion(final String fieldName, final Object[] fieldValues, String otherField, final MatchType matchType) { Assert.hasText(fieldName, "fieldName不能为空"); Criterion criterion = null; try { // 根据MatchType构造criterion if (MatchType.EQ.equals(matchType)) { criterion = Restrictions.eq(fieldName, fieldValues[0]); } else if (MatchType.LE.equals(matchType)) { criterion = Restrictions.le(fieldName, fieldValues[0]); } else if (MatchType.LT.equals(matchType)) { criterion = Restrictions.lt(fieldName, fieldValues[0]); } else if (MatchType.GE.equals(matchType)) { criterion = Restrictions.ge(fieldName, fieldValues[0]); } else if (MatchType.GT.equals(matchType)) { criterion = Restrictions.gt(fieldName, fieldValues[0]); } else if (MatchType.NE.equals(matchType)) { criterion = Restrictions.ne(fieldName, fieldValues[0]); } else if (MatchType.EQF.equals(matchType)) { criterion = Restrictions.eqProperty(fieldName, otherField); } else if (MatchType.LEF.equals(matchType)) { criterion = Restrictions.leProperty(fieldName, otherField); } else if (MatchType.LTF.equals(matchType)) { criterion = Restrictions.ltProperty(fieldName, otherField); } else if (MatchType.GEF.equals(matchType)) { criterion = Restrictions.geProperty(fieldName, otherField); } else if (MatchType.GTF.equals(matchType)) { criterion = Restrictions.gtProperty(fieldName, otherField); } else if (MatchType.NEF.equals(matchType)) { criterion = Restrictions.neProperty(fieldName, otherField); } else if (MatchType.LIKE.equals(matchType)) { criterion = Restrictions.like(fieldName, (String) fieldValues[0], MatchMode.EXACT); } else if (MatchType.LIKE_START.equals(matchType)) { criterion = Restrictions.like(fieldName, (String) fieldValues[0], MatchMode.START); } else if (MatchType.LIKE_END.equals(matchType)) { criterion = Restrictions.like(fieldName, (String) fieldValues[0], MatchMode.END); } else if (MatchType.LIKE_ANYWHERE.equals(matchType)) { criterion = Restrictions.like(fieldName, (String) fieldValues[0], MatchMode.ANYWHERE); } else if (MatchType.BETWEEN.equals(matchType)) { criterion = Restrictions.between(fieldName, fieldValues[0], fieldValues[1]); } } catch (Exception e) { throw ReflectionUtils.convertReflectionExceptionToUnchecked(e); } return criterion; } /** * 按属性条件参数创建Criterion,辅助函数. */ protected Criterion buildFieldFilterCriterion(PropertyFilter filter) { return buildFieldFilterCriterion(filter.getFieldName(), filter.getValues(), filter.getOtherField(), filter.getMatchType()); } /** * 判断对象的属性值在数据库内是否唯一. * * 在修改对象的情景下,如果属性新修改的值(value)等于属性原来的值(orgValue)则不作比较. */ public boolean isFieldUnique(final String fieldName, final Object newValue, final Object oldValue) { if (newValue == null || newValue.equals(oldValue)) { return true; } Object object = findUniqueBy(fieldName, newValue); return (object == null); } }
事例:
public Setting getSetting(String key) { List<FieldFilter> filters = new ArrayList<FieldFilter>(); FieldFilter ff1 = new FieldFilter("keyField", "data", MatchType.EQF); FieldFilter ff2 = new FieldFilter("data", MatchType.BETWEEN, "3", "6"); FieldFilter ff3 = new FieldFilter("data", MatchType.BETWEEN, "4", "8"); ff1.addRoundAndFilter(ff2); ff2.addOrFilter(ff3); filters.add(ff1); settingDao.find(filters); return null; }
生成sql
select
this_.keyField as keyField0_0_,
this_.version as version0_0_,
this_.data as data0_0_,
this_.description as descript4_0_0_,
this_.orderby as orderby0_0_
from
setting this_
where
(
this_.keyField=this_.data
and this_.data between ? and ?
)
or this_.data between ? and ?