QueryBuilder的构建

来源:互联网 发布:淘宝加钱换购退货 编辑:程序博客网 时间:2024/06/12 23:44
package com.nti.lmis.util.dao;

import com.nti.lmis.util.common.StringFormatUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import org.joda.time.LocalTime;
import org.joda.time.TimeOfDay;
import org.joda.time.YearMonthDay;
import org.joda.time.base.AbstractInstant;

import java.util.ArrayList;
import java.util.List;

public final class QueryBuilder {
    static private Log LOG = LogFactory.getLog(QueryBuilder.class);
    static public final String LINE_SEPARATOR = System.getProperty("line.separator");
    private StringBuffer _queryStringBuf = new StringBuffer();
    private List<Object> _parameters = new ArrayList<Object>();
    private boolean _startedWhereClause = false;

    /**
     * 构造函数
     */
    public QueryBuilder() {
    }

    /**
     * 构造函数
     *
     * @param s hql语句
     */
    public QueryBuilder(String s) {
        _queryStringBuf.append(s);
    }

    /**
     * 连接hql字符串
     *
     * @param s hql字符串
     */
    public void append(String s) {
        _queryStringBuf.append(s);
    }

    /**
     * 追加like字符串,忽略大小写
     *
     * @param property 属性
     * @param value    值
     */
    public void appendLikeIgnoreCase(String property, String value) {
        if (!StringFormatUtil.isEmpty(value)) {
            appendLike("lower(" + property + ")", (value == null ? null : value
                    .toLowerCase()));
        }
    }

    /**
     * 追加like字符串,不忽略大小写,前匹配
     *
     * @param property 属性
     * @param value    值
     */
    public void appendLike(String property, String value) {
        if (!StringFormatUtil.isEmpty(value)) {
            _queryStringBuf.append(whereOrAnd());
            _queryStringBuf.append(" ").append(property).append(" like ?");
            _parameters.add(value + "%");
        }
    }

    /**
     * 追加like字符串,不忽略大小写,全部模糊匹配
     *
     * @param property 属性
     * @param value    值
     */
    public void appendLikeAll(String property, String value) {
        if (!StringFormatUtil.isEmpty(value)) {
            _queryStringBuf.append(whereOrAnd());
            _queryStringBuf.append(" ").append(property).append(" like ?");
            _parameters.add("%" + value + "%");
        }
    }

    /**
     * 追加相等某属性,可忽略空值
     *
     * @param property           属性
     * @param value              属性对应的值
     * @param ignoreIfValueEmpty true 忽略空值,false 不忽略
     */
    public void appendEqualsIgnoreCase(String property, String value, boolean ignoreIfValueEmpty) {
        if (!ignoreIfValueEmpty || !StringFormatUtil.isEmpty(value)) {
            appendEquals("lower(" + property + ")", (value == null ? null : value.toLowerCase()));
        }
    }

    /**
     * 为hql追加相等处理对象值,可忽略空值
     *
     * @param property           属性
     * @param value              属性值
     * @param ignoreIfValueEmpty 是否忽略空值
     */
    @SuppressWarnings("unchecked")
    public void appendEquals(String property, Object value, boolean ignoreIfValueEmpty) {
        if (value == null) {
            if (!ignoreIfValueEmpty) {
                appendEquals(property, value);
            }
        } else if (value instanceof List) {
            if (((List) value).size() > 0) {
                appendIn(property, (List<Object>) value);
            }
        } else if (value instanceof String) {
            if (!ignoreIfValueEmpty || !value.equals("")) {
                appendEquals(property, value);
            }
        } else {
            appendEquals(property, value);
        }
    }

    /**
     * 附加in处理值
     *
     * @param property 属性
     * @param values   值
     */
    public void appendIn(String property, List<Object> values) {
        if (values.size() > 0) {
            _queryStringBuf.append(whereOrAnd());
            _queryStringBuf.append(" (");

            for (int i = 0; i < values.size(); i++) {
                if (i != 0) {
                    _queryStringBuf.append(" or");
                }

                Object value = values.get(i);
                _queryStringBuf.append(" ").append(property).append(" = ?");
                _parameters.add(downcast(value));
            }

            if (values.size() > 0) {
                _queryStringBuf.append(")");
            }
        }
    }

    /**
     * 附加in处理值
     *
     * @param property 属性
     * @param values   值
     */
    public void appendIn(String property, Object[] values) {
        if (values.length > 0) {
            _queryStringBuf.append(whereOrAnd());
            _queryStringBuf.append(" (");

            for (int i = 0; i < values.length; i++) {
                if (i != 0) {
                    _queryStringBuf.append(" or");
                }

                Object value = values[i];
                _queryStringBuf.append(" ").append(property).append(" = ?");
                _parameters.add(downcast(value));
            }

            if (values.length > 0) {
                _queryStringBuf.append(")");
            }
        }
    }

    /**
     * 追加一个数学运算符到hql语句.
     *
     * @param property           属性
     * @param comparisonOperator 操作符
     * @param value              值
     */
    public void appendComparison(String property, ComparisonOperator comparisonOperator, Object value) {
        if (value != null) {
            _queryStringBuf.append(whereOrAnd());

            switch (comparisonOperator) {
                case LT:
                    _queryStringBuf.append(" ").append(property).append(" < ?");
                    break;
                case LE:
                    _queryStringBuf.append(" ").append(property).append(" <= ?");
                    break;
                case EQ:
                    _queryStringBuf.append(" ").append(property).append(" = ?");
                    break;
                case GE:
                    _queryStringBuf.append(" ").append(property).append(" >= ?");
                    break;
                case GT:
                    _queryStringBuf.append(" ").append(property).append(" > ?");
                    break;
                case NE:
                    _queryStringBuf.append(" ").append(property).append(" <> ?");
                    break;
                default:
                    throw new IllegalStateException("comparisonOperator = " + comparisonOperator);
            }

            _parameters.add(downcast(value));
        }
    }

    /**
     * 追加一个范围值到hql
     *
     * @param property      属性
     * @param fromValue     开始值
     * @param toValue       结束值
     * @param includeEquals true 包含,false 不包含
     */
    public void appendBetween(String property, Object fromValue, Object toValue, boolean includeEquals) {
        if ((fromValue != null) || (toValue != null)) {
            if (fromValue != null) {
                _queryStringBuf.append(whereOrAnd());

                if (includeEquals) {
                    _queryStringBuf.append(" ").append(property)
                            .append(" >= ?");
                } else {
                    _queryStringBuf.append(" ").append(property).append(" > ?");
                }

                _parameters.add(downcast(fromValue));
            }

            if (toValue != null) {
                _queryStringBuf.append(whereOrAnd());
                if (includeEquals) {
                    _queryStringBuf.append(" ").append(property)
                            .append(" <= ?");
                } else {
                    _queryStringBuf.append(" ").append(property).append(" < ?");
                }
                _parameters.add(downcast(toValue));
            }
        }
    }

    /**
     * 获取最终的hql语句
     *
     * @return hql语句
     */
    public String getQueryString() {
        return _queryStringBuf.toString();
    }

    /**
     * 获取所有查询参数
     *
     * @return 参数数组
     */
    public Object[] getParameters() {
        return _parameters.toArray();
    }

    /**
     * 重写字符串转换函数
     *
     * @return hql语句
     */
    public String toString() {
        StringBuffer buf = new StringBuffer();
        buf.append("Query string = \"").append(_queryStringBuf.toString())
                .append("\"").append(LINE_SEPARATOR);
        buf.append("Parameters = { ");

        for (Object parameter : _parameters) {
            buf.append("[");
            if (parameter instanceof String) {
                buf.append("\"").append(parameter.toString()).append("\"");
            } else {
                buf.append(parameter.getClass().getName()).append(": ").append(parameter.toString());
            }
            buf.append("] ");
        }

        buf.append(" }");
        return buf.toString();
    }

    /**
     * 追加排序处理
     *
     * @param options      查询项
     * @param objectPrefix 对象前缀
     */
    public void appendOrderBy(SearchOptions options, String objectPrefix) {
        _queryStringBuf.append(createOrderByClause(options, objectPrefix));
    }

    /**
     * 追加相等处理对象值
     *
     * @param property 属性
     * @param value    值
     */
    private void appendEquals(String property, Object value) {
        _queryStringBuf.append(whereOrAnd());
        _queryStringBuf.append(" ").append(property).append(" = ?");
        _parameters.add(downcast(value));
    }

    private String createOrderByClause(SearchOptions options,
                                       String objectPrefix) {
        StringBuffer buf = new StringBuffer();
        int index = 0;
        boolean firstOrder = true;

        for (String sortColumnName : options.getSortColumnNames()) {
            if (!StringFormatUtil.isEmpty(sortColumnName)) {
                if (firstOrder) {
                    firstOrder = false;
                    buf.append(" order by");
                } else {
                    buf.append(",");
                }
                buf.append(" ").append(objectPrefix).append(".").append(
                        sortColumnName);
                buf.append(options.isSortAscending(index) ? " asc" : " desc");
            }
            index++;
        }

        return buf.toString();
    }

    private String whereOrAnd() {
        if (_startedWhereClause) {
            return " and";
        } else {
            _startedWhereClause = true;
            return " where";
        }
    }

    private Object downcast(Object obj) {
        Object out = obj;

        try {
            if (obj != null) {
                if (obj instanceof AbstractInstant) {
                    out = ((AbstractInstant) obj).toDate();
                } else if (obj instanceof LocalTime) {
                    out = ((YearMonthDay) obj).toDateMidnight().toDate();
                } else if (obj instanceof TimeOfDay) {
                    out = ((TimeOfDay) obj).toDateTime(new DateTime(0)).toDate();
                }
            }
        } catch (ClassCastException ccEx) {
            LOG.info(ccEx.fillInStackTrace());
        }

        return out;
    }
}