• GitHub项目:jkrasnay/sqlbuilder的使用


    http://www.jianshu.com/p/7f099b8cf5f0

    技术选型:

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

    在老项目中使用的是一种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

  • 相关阅读:
    Android 入门到精通 (Index)
    负载平衡与冗余备份方案概述
    Android 程序组件交互分析
    复制时保留文件的目录结构
    notepad++中设置tab缩进的宽度
    scws
    php 将字符(包括汉字) 转换成16进制 (apache access log 中文显示16进制码)
    批量修改完整版本
    根据端口号查进程
    php性能优化
  • 原文地址:https://www.cnblogs.com/victor2302/p/7566965.html
Copyright © 2020-2023  润新知