美文网首页报表开发、图表开发与数据分析
GitHub项目:jkrasnay/sqlbuilder的使用

GitHub项目:jkrasnay/sqlbuilder的使用

作者: 聚变 | 来源:发表于2017-09-20 15:52 被阅读196次
    image.png

    技术选型:

    在报表查询时,通常需要做可以动态添加的条件

    在老项目中使用的是一种Tcondition的对象分装sql

    
    import java.util.HashMap;
    
    public class TCondition {
    
        private String sql;
    
        private Object[] paraValues;
    
        private String orderBy;
    
        private String groupBy;
    
        private String having;
    
        /**
         * key为表名,value为 left join on后的内容(如何关联的)
         */
        private HashMap<String,String> leftJoinMap;
    
        /**
         * count方法计数时可指定 count哪个字段,默认为count(1)
         */
        private String mainId;
    
        public TCondition() {
    
        }
    
        public TCondition(String sql, Object... paraValues) {
            this.setSql(sql);
            this.setParaValues(paraValues);
        }
    
        public static TCondition of() {
            return new TCondition();
        }
    
        public static TCondition of(String sql, Object... paraValues) {
            return new TCondition(sql, paraValues);
        }
    
        public String getSql() {
            return sql;
        }
    
        public TCondition setSql(String sql) {
            this.sql = sql;
            return this;
        }
    
        public Object[] getParaValues() {
            return paraValues;
        }
    
        public TCondition setParaValues(Object[] paraValues) {
            this.paraValues = paraValues;
            return this;
        }
    
        public String getOrderBy() {
            return orderBy;
        }
    
        public TCondition setOrderBy(String orderBy) {
            this.orderBy = orderBy;
            return this;
        }
    
        public String getGroupBy() {
            return groupBy;
        }
    
        public TCondition setGroupBy(String groupBy) {
            this.groupBy = groupBy;
            return this;
        }
    
        public String getHaving() {
            return having;
        }
    
        public TCondition setHaving(String having) {
            this.having = having;
            return this;
        }
    
        public String getMainId() {
            return mainId;
        }
    
        public TCondition setMainId(String mainId) {
            this.mainId = mainId;
            return this;
        }
    
        @Override
        public String toString() {
            StringBuffer result = new StringBuffer(this.getSql() + ":");
            for (int i = 0; i < paraValues.length; i++) {
                result.append(paraValues[i]).append(",");
            }
            result.append(" || ");
            return result.toString();
        }
    
        public HashMap<String, String> getLeftJoinMap() {
            return leftJoinMap;
        }
    
        public TCondition setLeftJoinMap(HashMap<String, String> leftJoinMap) {
            this.leftJoinMap = leftJoinMap;
            return this;
        }
    

    但是由于与老代码的数据库访问层紧紧的耦合在一起,无法在另外的项目中进行复用,因此,在GitHub中找到了一款类似的封装SQL查询的对象

    封装的内容:

    package ca.krasnay.sqlbuilder;
    
    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Tool for programmatically constructing SQL select statements. This class aims
     * to simplify the task of juggling commas and SQL keywords when building SQL
     * statements from scratch, but doesn't attempt to do much beyond that. Here are
     * some relatively complex examples:
     *
     * <pre>
     * String sql = new SelectBuilder()
     * .column("e.id")
     * .column("e.name as empname")
     * .column("d.name as deptname")
     * .column("e.salary")
     * .from(("Employee e")
     * .join("Department d on e.dept_id = d.id")
     * .where("e.salary > 100000")
     * .orderBy("e.salary desc")
     * .toString();
     * </pre>
     *
     * <pre>
     * String sql = new SelectBuilder()
     * .column("d.id")
     * .column("d.name")
     * .column("sum(e.salary) as total")
     * .from("Department d")
     * .join("Employee e on e.dept_id = d.id")
     * .groupBy("d.id")
     * .groupBy("d.name")
     * .having("total > 1000000").toString();
     * </pre>
     *
     * Note that the methods can be called in any order. This is handy when a base
     * class wants to create a simple query but allow subclasses to augment it.
     *
     * It's similar to the Squiggle SQL library
     * (http://code.google.com/p/squiggle-sql/), but makes fewer assumptions about
     * the internal structure of the SQL statement, which I think makes for simpler,
     * cleaner code. For example, in Squiggle you would write...
     *
     * <pre>
     * select.addCriteria(new MatchCriteria(orders, "status", MatchCriteria.EQUALS, "processed"));
     * </pre>
     *
     * With SelectBuilder, we assume you know how to write SQL expressions, so
     * instead you would write...
     *
     * <pre>
     * select.where("status = 'processed'");
     * </pre>
     *
     * To include parameters, it's highly recommended to use the
     * {@link ParameterizedPreparedStatementCreatorTest}, like this:
     *
     * <pre>
     * String sql = new SelectBuilder("Employee e")
     * .where("name like :name")
     * .toString();
     *
     * PreparedStatement ps = new ParameterizedPreparedStatementCreator(sql)
     * .setParameter("name", "Bob%")
     * .createPreparedStatement(conn);
     * </pre>
     *
     *
     * @author John Krasnay <john@krasnay.ca>
     */
    public class SelectBuilder extends AbstractSqlBuilder implements Cloneable, Serializable {
    
        private static final long serialVersionUID = 1;
    
        private boolean distinct;
    
        private List<Object> columns = new ArrayList<Object>();
    
        private List<String> tables = new ArrayList<String>();
    
        private List<String> joins = new ArrayList<String>();
    
        private List<String> leftJoins = new ArrayList<String>();
    
        private List<String> wheres = new ArrayList<String>();
    
        private List<String> groupBys = new ArrayList<String>();
    
        private List<String> havings = new ArrayList<String>();
    
        private List<SelectBuilder> unions = new ArrayList<SelectBuilder>();
    
        private List<String> orderBys = new ArrayList<String>();
    
        private boolean forUpdate;
    
        private boolean noWait;
    
        public SelectBuilder() {
    
        }
    
        public SelectBuilder(String table) {
            tables.add(table);
        }
    
        /**
         * Copy constructor. Used by {@link #clone()}.
         *
         * @param other
         *            SelectBuilder being cloned.
         */
        protected SelectBuilder(SelectBuilder other) {
    
            this.distinct = other.distinct;
            this.forUpdate = other.forUpdate;
            this.noWait = other.noWait;
    
            for (Object column : other.columns) {
                if (column instanceof SubSelectBuilder) {
                    this.columns.add(((SubSelectBuilder) column).clone());
                } else {
                    this.columns.add(column);
                }
            }
    
            this.tables.addAll(other.tables);
            this.joins.addAll(other.joins);
            this.leftJoins.addAll(other.leftJoins);
            this.wheres.addAll(other.wheres);
            this.groupBys.addAll(other.groupBys);
            this.havings.addAll(other.havings);
    
            for (SelectBuilder sb : other.unions) {
                this.unions.add(sb.clone());
            }
    
            this.orderBys.addAll(other.orderBys);
        }
    
        /**
         * Alias for {@link #where(String)}.
         */
        public SelectBuilder and(String expr) {
            return where(expr);
        }
    
        public SelectBuilder column(String name) {
            columns.add(name);
            return this;
        }
    
        public SelectBuilder column(SubSelectBuilder subSelect) {
            columns.add(subSelect);
            return this;
        }
    
        public SelectBuilder column(String name, boolean groupBy) {
            columns.add(name);
            if (groupBy) {
                groupBys.add(name);
            }
            return this;
        }
    
        @Override
        public SelectBuilder clone() {
            return new SelectBuilder(this);
        }
    
        public SelectBuilder distinct() {
            this.distinct = true;
            return this;
        }
    
        public SelectBuilder forUpdate() {
            forUpdate = true;
            return this;
        }
    
        public SelectBuilder from(String table) {
            tables.add(table);
            return this;
        }
    
        public List<SelectBuilder> getUnions() {
            return unions;
        }
    
        public SelectBuilder groupBy(String expr) {
            groupBys.add(expr);
            return this;
        }
    
        public SelectBuilder having(String expr) {
            havings.add(expr);
            return this;
        }
    
        public SelectBuilder join(String join) {
            joins.add(join);
            return this;
        }
    
        public SelectBuilder leftJoin(String join) {
            leftJoins.add(join);
            return this;
        }
    
        public SelectBuilder noWait() {
            if (!forUpdate) {
                throw new RuntimeException("noWait without forUpdate cannot be called");
            }
            noWait = true;
            return this;
        }
    
        public SelectBuilder orderBy(String name) {
            orderBys.add(name);
            return this;
        }
    
        /**
         * Adds an ORDER BY item with a direction indicator.
         *
         * @param name
         *            Name of the column by which to sort.
         * @param ascending
         *            If true, specifies the direction "asc", otherwise, specifies
         *            the direction "desc".
         */
        public SelectBuilder orderBy(String name, boolean ascending) {
            if (ascending) {
                orderBys.add(name + " asc");
            } else {
                orderBys.add(name + " desc");
            }
            return this;
        }
    
        @Override
        public String toString() {
    
            StringBuilder sql = new StringBuilder("select ");
    
            if (distinct) {
                sql.append("distinct ");
            }
    
            if (columns.size() == 0) {
                sql.append("*");
            } else {
                appendList(sql, columns, "", ", ");
            }
    
            appendList(sql, tables, " from ", ", ");
            appendList(sql, joins, " join ", " join ");
            appendList(sql, leftJoins, " left join ", " left join ");
            appendList(sql, wheres, " where ", " and ");
            appendList(sql, groupBys, " group by ", ", ");
            appendList(sql, havings, " having ", " and ");
            appendList(sql, unions, " union ", " union ");
            appendList(sql, orderBys, " order by ", ", ");
    
            if (forUpdate) {
                sql.append(" for update");
                if (noWait) {
                    sql.append(" nowait");
                }
            }
    
            return sql.toString();
        }
    
        /**
         * Adds a "union" select builder. The generated SQL will union this query
         * with the result of the main query. The provided builder must have the
         * same columns as the parent select builder and must not use "order by" or
         * "for update".
         */
        public SelectBuilder union(SelectBuilder unionBuilder) {
            unions.add(unionBuilder);
            return this;
        }
    
        public SelectBuilder where(String expr) {
            wheres.add(expr);
            return this;
        }
    }
    
    在后续的文章中我将介绍如何使用该组件,在报表项目中进行使 ^_^
    
    

    github地址:

    https://github.com/jkrasnay/sqlbuilder

    博客:

    http://john.krasnay.ca/2010/02/15/building-sql-in-java.html

    相关文章

      网友评论

        本文标题:GitHub项目:jkrasnay/sqlbuilder的使用

        本文链接:https://www.haomeiwen.com/subject/gttbsxtx.html