|
<!--前段时间看到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工具类实现,代码还有待改进 |
|