All Downloads are FREE. Search and download functionalities are using the official Maven repository.

top.jfunc.common.db.query.AbstractQueryBuilder Maven / Gradle / Ivy

package top.jfunc.common.db.query;

import top.jfunc.common.ChainCall;
import top.jfunc.common.db.condition.Criterion;
import top.jfunc.common.db.page.MySqlPageBuilder;
import top.jfunc.common.db.page.PageBuilder;
import top.jfunc.common.utils.CollectionUtil;
import top.jfunc.common.utils.Joiner;
import top.jfunc.common.utils.StrUtil;

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

import static top.jfunc.common.db.query.SqlUtil.*;

/**
 * SQL的模式
 *   SELECT .. FROM .. (LEFT|RIGHT|INNER) JOIN .. ON .. WHERE .... GROUP BY .. HAVING .. ORDER BY
 * @author xiongshiyan at 2019/12/12 , contact me with email [email protected] or phone 15208384257
 */
public abstract class AbstractQueryBuilder implements QueryBuilder, ChainCall {
    /**
     * select子句
     */
    protected String       selectClause;
    /**
     * from子句
     */
    protected StringBuilder fromClause    = new StringBuilder();
    /**
     * where子句
     */
    protected StringBuilder whereClause   = new StringBuilder();
    /**
     * group by子句
     */
    protected StringBuilder groupByClause = null;
    /**
     * having子句
     */
    protected StringBuilder havingClause  = null;
    /**
     * order by子句
     */
    protected StringBuilder orderByClause = null;

    /**
     * 默认-1表示没有分页参数
     */
    protected int pageNumber = -1;
    protected int pageSize = 10;

    private static PageBuilder DEFAULT_PAGE_BUILDER = MySqlPageBuilder.getInstance();
    /**
     * 全局设置pageBuilder
     * @param pageBuilder pageBuilder
     */
    public static void initDefaultPageBuilder(PageBuilder pageBuilder){
        DEFAULT_PAGE_BUILDER = pageBuilder;
    }
    /**
     * 分页参数处理器,默认是mysql的
     */
    protected PageBuilder pageBuilder = DEFAULT_PAGE_BUILDER;
    /**
     * 设置此pageBuilder
     * @param pageBuilder pageBuilder
     * @return this
     */
    public THIS setPageBuilder(PageBuilder pageBuilder) {
        this.pageBuilder = pageBuilder;
        return myself();
    }

    public PageBuilder getPageBuilder() {
        return pageBuilder;
    }

    //////////////////////////////////////1.构造方法,确定基本的表和查询字段/////////////////////////////////////

    public AbstractQueryBuilder(){}

    /**
     * 用于一张表的情况,生成From子句
     * from topic t
     */
    public AbstractQueryBuilder(String select, String tableName, String alias){
        this.selectClause = addSelectIfNecessary(select);
        fromClause.append(rightBlank(SqlKeyword.FROM.getKeyword())).append(tableName).append(BLANK).append(alias);
    }

    /**
     * 用于两张表联合的情况,生成From子句,类似from table1 a,table2 b 然后添加where条件
     * 另外像left join 这种可以写在一个from字句中或者使用 leftJoin rightJoin innerJoin方法
     */
    public AbstractQueryBuilder(String select, String... froms){
        this.selectClause = addSelectIfNecessary(select);
        String prefix = rightBlank(SqlKeyword.FROM.getKeyword());
        //if(INCLUDE_FROM.matcher(froms[0]).matches()){
        //去除空格取前5个[from ]
        if(startsWith(froms[0] , prefix)){
            prefix = BLANK ;
        }
        fromClause.append(prefix).append(Joiner.on(COMMA).join(froms));
    }
    private String addSelectIfNecessary(String select) {
        //if(INCLUDE_SELECT.matcher(select).matches()){
        //去除空格取前6个[select ]
        String selectRightBlank = rightBlank(SqlKeyword.SELECT.getKeyword());
        if(startsWith(select , selectRightBlank)){
            //包含了select
            return select;
        }else {
            //没有包含select
            return selectRightBlank + select;
        }
    }

    public THIS setSelectClause(CharSequence selectClause) {
        this.selectClause = selectClause.toString();
        return myself();
    }

    public THIS setFromClause(CharSequence fromClause) {
        this.fromClause = new StringBuilder(fromClause);
        return myself();
    }

    //////////////////////////////////////2.1.leftJoin方法,添加LEFT JOIN子句/////////////////////////////////////

    /**
     * 添加left join子句
     * @param joinClause LEFT JOIN 子句
     * @param onClause on条件 有一个添加在后面 , 不要带 ON 了 , 没有必须使用on方法添加
     */
    @Override
    public THIS leftJoin(String joinClause , String onClause){
        leftJoin(joinClause);
        on(onClause);
        return myself();
    }
    @Override
    public THIS leftJoin(String joinClause){
        String leftJoin = leftRightBlank(SqlKeyword.LEFT_JOIN.getKeyword());
        fromClause.append(leftJoin).append(joinClause);
        return myself();
    }

    //////////////////////////////////////2.2.rightJoin方法,添加RIGHT JOIN子句/////////////////////////////////////

    /**
     * 添加right join子句
     * @param joinClause RIGHT JOIN 子句
     */
    @Override
    public THIS rightJoin(String joinClause , String onClause){
        rightJoin(joinClause);
        on(onClause);
        return myself();
    }
    @Override
    public THIS rightJoin(String joinClause){
        String rightJoin = leftRightBlank(SqlKeyword.RIGHT_JOIN.getKeyword());
        fromClause.append(rightJoin).append(joinClause);
        return myself();
    }

    //////////////////////////////////////2.3.innerJoin方法,添加INNER JOIN子句/////////////////////////////////////

    /**
     * 添加inner join子句
     * @param joinClause INNER JOIN 子句
     */
    @Override
    public THIS innerJoin(String joinClause , String onClause){
        innerJoin(joinClause);
        on(onClause);
        return myself();
    }
    @Override
    public THIS innerJoin(String joinClause){
        String innerJoin = leftRightBlank(SqlKeyword.INNER_JOIN.getKeyword());
        fromClause.append(innerJoin).append(joinClause);
        return myself();
    }

    //////////////////////////////////////2.4.on方法,join子句添加on条件/////////////////////////////////////

    /**
     * 添加on子句 , 不要带ON 了 , 可以被 left、right、inner join子句使用  , 但是必须紧跟在JOIN 子句后面
     * @param onClause ON 子句
     */
    @Override
    public THIS on(String onClause){
        String on = leftRightBlank(SqlKeyword.ON.getKeyword());
        fromClause.append(on).append(onClause);
        return myself();
    }

    ////////////////////////////3.addCondition/and/andIf 方法,添加条件,多个用 AND 连接////////////////////////////

    /**
     * 拼接where子句 d.id between ? and ?   d.parent=?    d.parent is null
     * 跟 and(String, Object...) 的意义完全一致
     * @see THIS#and(String, Object...)
     * @param condition 具体条件
     * @param params 参数,THIS只支持?参数,如果你想用Query的具名参数,就不要设置参数,产生{Query}后再调用setParameter设置
     */
    @Override
    public THIS addCondition(String condition, Object... params){
        // 拼接条件
        addWhereAndCondition(condition);
        // 添加参数
        addParams(params);
        return myself();
    }

    @Override
    public THIS addCondition(boolean append, String condition, Object... params) {
        if(append){
            addCondition(condition, params);
        }
        return myself();
    }

    @Override
    public THIS addCondition(Criterion criterion) {
        addCondition(criterion.toJdbcSql(), criterion.getParameters().toArray());
        return myself();
    }

    @Override
    public THIS and(String condition, Object... params) {
        return addCondition(condition , params);
    }

    @Override
    public THIS and(boolean append, String condition, Object... params) {
        if(append){
            addCondition(condition, params);
        }
        return myself();
    }

    ////////////////////////////4.or/orNew/orIf/orNewIf方法,添加条件,多个用 OR 连接////////////////////////////

    /**
     * 添加 OR 子句
     */
    @Override
    public THIS or(String condition, Object... params){
        // 添加OR子句
        addOrCondition(condition);
        // 添加参数
        addParams(params);
        return myself();
    }

    @Override
    public THIS or(boolean append, String condition, Object... params) {
        if(append){
            or(condition, params);
        }
        return myself();
    }

    protected void addOrCondition(String condition) {
        //OR 子句一般来说不是第一个,所以此时肯定存在了 WHERE
        int index = whereClause.toString().toUpperCase().indexOf(SqlKeyword.WHERE.getKeyword());
        if(-1 == index){
            throw new RuntimeException("还没有条件,不能使用or方法");
        }

        String or = leftRightBlank(SqlKeyword.OR.getKeyword());
        whereClause.append(or).append(condition);
    }

    @Override
    public THIS orNew(String condition, Object... params){
        addOrNewCondition(condition);
        addParams(params);
        return myself();
    }

    @Override
    public THIS orNew(boolean append, String condition, Object... params) {
        if(append){
            orNew(condition, params);
        }
        return myself();
    }

    protected void addOrNewCondition(String condition) {
        //找到where
        int index = whereClause.toString().toUpperCase().indexOf(SqlKeyword.WHERE.getKeyword());
        if(-1 == index){
            throw new RuntimeException("还没有条件,不能使用orNew方法");
        }
        //以前的条件使用()包裹起来
        whereClause.insert(index + 6, LEFT_BRAKET).append(RIGHT_BRAKET);
        whereClause.append(leftRightBlank(SqlKeyword.OR.getKeyword()))
                .append(LEFT_BRAKET).append(condition).append(RIGHT_BRAKET);
    }

    /**
     * 增加 where ,如果存在就添加 and
     */
    protected void addWhere() {
        if(whereClause.length() == 0){
            String where = rightBlank(SqlKeyword.WHERE.getKeyword());
            whereClause.append(where);
        } else{
            String and = leftRightBlank(SqlKeyword.AND.getKeyword());
            whereClause.append(and);
        }
    }
    protected void addWhereAndCondition(String condition) {
        addWhere();
        whereClause.append(condition);
    }

    ///////////////////////////////////6.addIn/addInIf/addNotIn方法,添加 IN 条件/////////////////////////////////////////////

    @Override
    public  THIS addIn(String what , List ins){
        if(CollectionUtil.isEmpty(ins)){
            return myself();
        }

        inNotInClause(what, SqlKeyword.IN , ins);

        return myself();
    }

    @Override
    public  THIS addIn(String what, T... ins) {
        return addIn(what , Arrays.asList(ins));
    }

    @Override
    public  THIS addNotIn(String what, List ins) {
        if(CollectionUtil.isEmpty(ins)){
            return myself();
        }

        inNotInClause(what, SqlKeyword.NOT_IN , ins);

        return myself();
    }

    @Override
    public  THIS addNotIn(String what, T... ins) {
        return addNotIn(what , Arrays.asList(ins));
    }

    /**
     * in (...)  或者 not in (...)
     * @param sqlKeyword IN | NOT IN
     */
    private  void inNotInClause(String what, SqlKeyword sqlKeyword , List ins) {
        // 拼接where
        addWhere();
        // 添加左括号
        String in = leftRightBlank(sqlKeyword.getKeyword());
        whereClause.append(what).append(in).append(LEFT_BRAKET);

        ///
        /*for(Object part : ins){
            //数字不需要'' , 其他就转化为字符串并加上''
            String x = part instanceof Number ? part.toString() : QUOTE + part + QUOTE;
            whereClause.append(x).append(COMMA);
        }
        // 去掉最后的 ,
        whereClause = new StringBuilder(whereClause.substring(0 , whereClause.lastIndexOf(COMMA)));*/

        List parts = new ArrayList<>(ins.size());
        ins.forEach(ele->parts.add(StrUtil.QUESTION_MARK));
        String questions = Joiner.on(StrUtil.COMMA).join(parts);
        whereClause.append(questions);
        //添加右括号
        whereClause.append(RIGHT_BRAKET);

        addParams(ins.toArray());
    }

    @Override
    public THIS in(String what, String inSubQuery) {
        addWhere();
        whereClause.append(what).append(leftRightBlank(SqlKeyword.IN.getKeyword()))
                .append(LEFT_BRAKET).append(inSubQuery).append(RIGHT_BRAKET);
        return myself();
    }

    @Override
    public THIS notIn(String what, String inSubQuery) {
        addWhere();
        whereClause.append(what).append(leftRightBlank(SqlKeyword.NOT_IN.getKeyword()))
                .append(LEFT_BRAKET).append(inSubQuery).append(RIGHT_BRAKET);
        return myself();
    }

    @Override
    public THIS exists(String sql) {
        addWhereAndCondition(middleBlank(SqlKeyword.EXISTS.getKeyword() , LEFT_BRAKET + sql + RIGHT_BRAKET));
        return myself();
    }
    @Override
    public THIS notExists(String sql) {
        addWhereAndCondition(middleBlank(SqlKeyword.NOT_EXISTS.getKeyword() , LEFT_BRAKET + sql + RIGHT_BRAKET));
        return myself();
    }

    ///////////////////////////////////7.addOrderProperty方法,添加 ORDER BY 子句//////////////////////////////////

    /**
     * 拼接order by子句
     * @param propertyName 参与排序的属性名
     * @param asc true表示升序,false表示降序
     */
    @Override
    public THIS addOrderProperty(String propertyName, boolean asc){
        if(getOrderByClause().length() == 0){
            String orderBy = leftRightBlank(SqlKeyword.ORDER_BY.getKeyword());
            getOrderByClause().append(orderBy);
        } else{
            getOrderByClause().append(COMMA);
        }
        String ascStr = leftRightBlank(SqlKeyword.ASC.getKeyword());
        String descStr = leftRightBlank(SqlKeyword.DESC.getKeyword());
        getOrderByClause().append(propertyName).append(asc ? ascStr : descStr);
        return myself();
    }

    @Override
    public THIS addAscOrderProperty(String propertyName) {
        return addOrderProperty(propertyName , ASC);
    }

    @Override
    public THIS addAscOrderProperty(String... propertyNames) {
        for (String propertyName : propertyNames) {
            addAscOrderProperty(propertyName);
        }
        return myself();
    }

    @Override
    public THIS addDescOrderProperty(String propertyName) {
        return addOrderProperty(propertyName , DESC);
    }

    @Override
    public THIS addDescOrderProperty(String... propertyNames) {
        for (String propertyName : propertyNames) {
            addDescOrderProperty(propertyName);
        }
        return myself();
    }

    @Override
    public THIS addOrderProperty(boolean append, String propertyName, boolean asc) {
        if(append){
            addOrderProperty(propertyName, asc);
        }
        return myself();
    }

    @Override
    public THIS addAscOrderProperty(boolean append, String propertyName) {
        if(append){
            addOrderProperty(propertyName, ASC);
        }
        return myself();
    }

    @Override
    public THIS addDescOrderProperty(boolean append, String propertyName) {
        if(append){
            addOrderProperty(propertyName , DESC);
        }
        return myself();
    }

    ///////////////////////////////////8.addGroupProperty方法,添加 GROUP BY 子句//////////////////////////////////

    /**
     * 添加GROUP BY子句
     * @param groupByName group by
     */
    @Override
    public THIS addGroupProperty(String groupByName){
        if(getGroupByClause().length() == 0){
            String groupBy = rightBlank(SqlKeyword.GROUP_BY.getKeyword());
            getGroupByClause().append(groupBy).append(groupByName);
        } else{
            getGroupByClause().append(COMMA).append(groupByName);
        }
        return myself();
    }

    @Override
    public THIS addGroupProperty(String... groupByNames) {
        for (String groupByName : groupByNames) {
            addGroupProperty(groupByName);
        }
        return myself();
    }

    ///////////////////////////////////9.addHaving方法,添加 HAVING 子句//////////////////////////////////

    /**
     * @param having having子句
     * @param params 参数
     */
    @Override
    public THIS addHaving(String having , Object... params){
        addHavingClause(having);
        addParams(params);
        return myself();
    }

    @Override
    public THIS addHaving(boolean append, String having, Object... params) {
        if(append){
            addHaving(having , params);
        }
        return myself();
    }

    protected void addHavingClause(String having) {
        if(getHavingClause().length() == 0){
            String hav = rightBlank(SqlKeyword.HAVING.getKeyword());
            getHavingClause().append(hav).append(having);
        } else{
            String and = leftRightBlank(SqlKeyword.AND.getKeyword());
            getHavingClause().append(and).append(having);
        }
    }

    /**
     * 添加参数
     * @param params 参数
     */
    protected abstract void addParams(Object... params);

    @Override
    public THIS page(int pageNumber, int pageSize) {
        if(pageNumber<=0){
            throw new IllegalArgumentException("pageNumber must >= 1");
        }
        if(pageSize<=0){
            throw new IllegalArgumentException("pageSize must >= 1");
        }

        this.pageNumber = pageNumber;
        this.pageSize = pageSize;

        return myself();
    }


    ///////////////////////////////////10.get相关方法,获取到组装的SQL语句,可以处理和不处理参数//////////////////////////////////

    /**
     * 获取 select
     */
    @Override
    public String getSelect(){
        return selectClause;
    }

    /**
     * From后面的所有语句 , 没有处理 ?
     * @see THIS#getSqlExceptSelect()
     */
    @Override
    public String getSqlExceptSelectWithoutPadding(){
        StringBuilder builder = new StringBuilder(middleBlank(fromClause.toString() , whereClause.toString()).trim());
        if(null != groupByClause){
            builder.append(leftBlank(groupByClause.toString()));
        }
        if(null != havingClause){
            builder.append(leftBlank(havingClause.toString()));
        }
        if(null != orderByClause){
            builder.append(leftBlank(orderByClause.toString()));
        }
        return leftBlank(builder.toString());
    }
    /**
     * 获取最终拼装的SQL , 没有处理 ?
     * @see THIS#getSql()
     */
    @Override
    public String getSqlWithoutPadding(){
        //没有设置分页参数的情况下
        if(-1 == pageNumber){
            String sql = middleBlank(selectClause , getSqlExceptSelectWithoutPadding());
            return sql.trim();
        }

        return pageBuilder.sqlWithPage(selectClause , getSqlExceptSelectWithoutPadding() , pageNumber , pageSize);
    }

    /**
     * 获取生成的用于查询总记录数的SQL语句 , 没有处理 ?
     * @see THIS#getCountQuerySql()
     * @see THIS#getSqlWithoutPadding()
     */
    @Override
    public String getCountQuerySqlWithoutPadding(){
        StringBuilder builder = new StringBuilder(SqlKeyword.SELECT.getKeyword()).append(" COUNT(*) AS totalRow ").append(middleBlank(fromClause.toString() , whereClause.toString()).trim());
        if(null != groupByClause){
            builder.append(leftBlank(groupByClause.toString()));
        }
        if(null != havingClause){
            builder.append(leftBlank(havingClause.toString()));
        }
        return builder.toString();
    }



    public StringBuilder getOrderByClause() {
        if(null == orderByClause){
            orderByClause = new StringBuilder();
        }
        return orderByClause;
    }

    public StringBuilder getGroupByClause() {
        if(null == groupByClause){
            groupByClause = new StringBuilder();
        }
        return groupByClause;
    }

    public StringBuilder getHavingClause() {
        if(null == havingClause){
            havingClause = new StringBuilder();
        }
        return havingClause;
    }

    protected String leftBlank(String word){
        return SqlUtil.leftBlank(word);
    }
    protected String rightBlank(String word){
        return SqlUtil.rightBlank(word);
    }
    protected String middleBlank(String word1, String word2){
        return SqlUtil.middleBlank(word1, word2);
    }
    protected String leftRightBlank(String word){
        return SqlUtil.leftRightBlank(word);
    }

    @Override
    public String toString() {
        return getSqlWithoutPadding();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy