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

com.kqinfo.universal.comdao.core.SqlBuilder Maven / Gradle / Ivy

The newest version!
package com.kqinfo.universal.comdao.core;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.data.annotation.Transient;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author zpj
 */
@Slf4j
public class SqlBuilder {

    private static final String DOWN_COMMA = ", ";

    public static final char UP_COMMA = '`';

    private static final String AND = "AND ";

    private static final String SQL_ITEM = "sqlItem.";

    private static final String ID = "id";

    private static final String ORDER_BY = "ORDER BY";
    private static final String LIMIT = "LIMIT";

    /**
     * 插入的通用SQL
     *
     * @param params domain
     * @param     domain type
     * @return sql
     */
    public  String insert(T params) {
        Class cls = params.getClass();
        StringBuilder col = new StringBuilder();
        StringBuilder val = new StringBuilder();
        ReflectionUtils.doWithFields(cls, field -> {
            field.setAccessible(true);
            try {
                if (field.get(params) != null) {
                    col.append(UP_COMMA).append(tableFiled(field)).append(UP_COMMA).append(DOWN_COMMA);
                    val.append("#{").append(field.getName()).append("} ").append(DOWN_COMMA);
                } else {
                    if (field.isAnnotationPresent(TableId.class)) {
                        col.append(UP_COMMA).append(tableFiled(field)).append(UP_COMMA).append(DOWN_COMMA);
                        val.append("LAST_INSERT_ID(" + UP_COMMA).append(tableFiled(field)).append(UP_COMMA).append(") ").append(DOWN_COMMA);
                    }
                }

            } catch (IllegalAccessException e) {
                log.error(e.getMessage(), e);
                throw new RuntimeException(cls.getName() + " Class not allow accesss " + field.getName() + " Field ");
            }
        }, field -> !field.isAnnotationPresent(Transient.class));
        TableName tableName = cls.getAnnotation(TableName.class);
        StringBuilder sql = new StringBuilder(" INSERT INTO ").append(tableName.value());
        sql.append('(').append(col, 0, col.lastIndexOf(DOWN_COMMA)).append(") ");
        sql.append(" VALUES ");
        sql.append('(').append(val, 0, val.lastIndexOf(DOWN_COMMA)).append(") ");
        return sql.toString();
    }

    /**
     * 批量插入
     *
     * @param list list
     * @param   domain type
     * @return sql
     */
    public  String insertBatch(@Param("list") List list) {
        // 取第一个值,得到对应的field
        Object e = list.get(0);
        Class cls = e.getClass();
        TableName t = cls.getAnnotation(TableName.class);


        StringBuilder val = new StringBuilder();
        StringBuilder col = new StringBuilder();
        ReflectionUtils.doWithFields(cls, field -> {
            ReflectionUtils.makeAccessible(field);
            col.append(UP_COMMA).append(tableFiled(field)).append(UP_COMMA).append(DOWN_COMMA);
            val.append("#{" + SQL_ITEM).append(field.getName()).append("} ").append(DOWN_COMMA);
        }, field -> !field.isAnnotationPresent(Transient.class));


        StringBuilder sql = new StringBuilder(" INSERT INTO ").append(t.value());
        sql.append('(').append(col.substring(0, col.lastIndexOf(DOWN_COMMA))).append(") ");
        sql.append(" VALUES \n");
        StringBuilder tmp = new StringBuilder();
        tmp.append('(').append(val.substring(0, val.lastIndexOf(DOWN_COMMA))).append(") ");

        for (int i = 0; i < list.size(); i++) {
            sql.append(tmp.toString().replace(SQL_ITEM, "list[" + i + "]."));
            if (i < list.size() - 1) {
                sql.append(",\n");
            }

        }
        return sql.toString();

    }


    /**
     * 删除的通用SQL
     *
     * @param id  id
     * @param cls domain type
     * @return sql
     */
    public  String delete(@Param("id") T id, Class cls) {
        TableName t = cls.getAnnotation(TableName.class);
        return " DELETE FROM " + t.value() + whereKey(cls, true);

    }

    /**
     * 更新的通用SQL
     *
     * @param params domain
     * @param     domain type
     * @return sql
     */
    public  String update(T params) {
        Class cls = params.getClass();
        TableName t = cls.getAnnotation(TableName.class);
        String colVal = assembleVariableSql(params, DOWN_COMMA, true);

        return " UPDATE " + t.value() +
                " SET " + colVal.substring(0, colVal.lastIndexOf(DOWN_COMMA)) +
                whereKey(cls, false);
    }

    /**
     * @param cls        类
     * @param isParamsId 是否是显式的参数id值,
     * @return where sql
     */
    private String whereKey(Class cls, boolean isParamsId) {
        Field field = this.getIdFiled(cls);
        if (field == null) {
            return " WHERE `id` = #{id} ";
        } else {
            if (isParamsId) {
                return " WHERE " + UP_COMMA + tableFiled(field) + UP_COMMA + " = #{id} ";
            } else {
                return " WHERE " + UP_COMMA + tableFiled(field) + UP_COMMA + " = #{" + field.getName() + "} ";
            }
        }
    }

    public Field getIdFiled(Class cls){
        AtomicReference idField = new AtomicReference<>();
        ReflectionUtils.doWithFields(cls, idField::set, field -> field.isAnnotationPresent(TableId.class));
        return idField.get();
    }


    /**
     * 根据id查单个对象
     *
     * @param id id
     * @param cls domain class
     * @param  domain type
     * @return sql
     */
    public  String select(@Param("id") T id, Class cls) {
        TableName t = cls.getAnnotation(TableName.class);
        return " SELECT * FROM " + t.value() + whereKey(cls, true);
    }


    public  String selectList(T params) {
        Class cls = params.getClass();

        String colVal = assembleVariableSql(params, AND, false);

        TableName t = cls.getAnnotation(TableName.class);
        StringBuilder sql = new StringBuilder();
        sql.append(" SELECT * FROM ").append(t.value());

        if (colVal.length() > 0) {
            sql.append(" WHERE ");
            sql.append(colVal, 0, colVal.lastIndexOf(AND));
        }
        return sql.toString();
    }


    public  String selectListByFieldFilter(T params, String[] fieldNames, boolean select) {

        String str = selectList(params);
        if (fieldNames != null && fieldNames.length > 0) {
            Set fieldMap = Stream.of(fieldNames).collect(Collectors.toSet());
            //在字段列表里的字段和没在字段列表里的字段,核心工作是验证代入字段的有效性
            List inList = new ArrayList<>();
            List outList = new ArrayList<>();

            ReflectionUtils.doWithFields(params.getClass(), field -> {
                // 找出filedNames中的field
                String fieldName = tableFiled(field);
                if (fieldMap.contains(fieldName)) {
                    inList.add(fieldName);
                }else {
                    outList.add(fieldName);
                }
            }, field -> !field.isAnnotationPresent(Transient.class));

            StringBuffer queryFieldNamesBuffer = new StringBuffer();
            if (select) {
                if (inList.size() > 0) {
                    generateFieldString(queryFieldNamesBuffer, inList);
                    str = str.replace("*", queryFieldNamesBuffer.toString());
                }
            } else {
                if (outList.size() > 0) {
                    generateFieldString(queryFieldNamesBuffer, outList);
                    str = str.replace("*", queryFieldNamesBuffer.toString());
                }
            }

        }
        return str;
    }


    private void generateFieldString(StringBuffer sbf, List fields) {
        for (int i = 0; i < fields.size(); i++) {
            if (i != fields.size() - 1) {
                sbf.append(UP_COMMA).append(fields.get(i)).append(UP_COMMA).append(DOWN_COMMA);
            } else {
                sbf.append(UP_COMMA).append(fields.get(i)).append(UP_COMMA);
            }
        }
    }


    /**
     * 组合更新的字段和查询所需要的字段
     *
     * @param params   参数对象
     * @param symbol   分隔符号
     * @param isUpdate 是否为插入语句
     * @return sql
     */
    private  String assembleVariableSql(T params, String symbol, boolean isUpdate) {
        Class cls = params.getClass();
        StringBuilder colVal = new StringBuilder();
        ReflectionUtils.doWithFields(cls, field -> {
            field.setAccessible(true);
            try {
                if (field.get(params) != null) {
                    if (!isUpdate && String.class == field.getType()) {
                        colVal.append(UP_COMMA).append(tableFiled(field)).append(UP_COMMA).append(" like #{").append(field.getName()).append("} ").append(symbol);
                    } else {
                        if (!(ID.equals(field.getName()) || field.getAnnotation(TableId.class) != null)) {
                            colVal.append(UP_COMMA).append(tableFiled(field)).append(UP_COMMA).append(" = #{").append(field.getName()).append("} ").append(symbol);
                        }
                    }
                }
            } catch (IllegalAccessException e) {
                log.error(e.getMessage(), e);
                throw new RuntimeException(cls.getName() + " Class not allow accesss " + field.getName() + " Field ");
            }
        }, f -> !f.isAnnotationPresent(Transient.class));
        return colVal.toString();
    }


    /**
     * 产生批处理SQL
     *
     * @param ids id列表
     * @param cls domain class
     * @param  domain type
     * @return sql
     */
    public  String deleteBatch(T[] ids, Class cls) {

        TableName t = cls.getAnnotation(TableName.class);

        String where = whereKey(cls, true);
        where = where.substring(0, where.indexOf('='));

        StringBuilder sql = new StringBuilder();
        sql.append(" DELETE FROM ").append(t.value()).append(where).append(" in ");
        sql.append(" ( ");

        if (ids != null && ids.length > 0) {
            StringBuilder colVal = new StringBuilder();
            for (T id : ids) {
                if (Integer.class == id.getClass() || Long.class == id.getClass()) {
                    colVal.append(id).append(DOWN_COMMA);
                } else if (String.class == id.getClass()) {
                    colVal.append('\'').append(id).append('\'').append(DOWN_COMMA);
                }
            }
            sql.append(colVal);
            sql.deleteCharAt(sql.lastIndexOf(DOWN_COMMA));
        } else {
            throw new RuntimeException("ids不能为空,且长度不能为0");
        }

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


    /**
     * 产生查询数量的SQL
     *
     * @param params domain
     * @param  domain type
     * @return sql
     */
    public  String selectCount(T params) {
        String str = selectList(params).replace("SELECT *", "SELECT COUNT(*)");
        if (str.contains(ORDER_BY)) {
            str = str.substring(0, str.indexOf(ORDER_BY));
        }
        if (str.contains(LIMIT)) {
            str = str.substring(0, str.indexOf(LIMIT));
        }
        return str;
    }


    public  String replace(T params) {
        return insert(params).replace("INSERT ", "REPLACE ");
    }

    public  String replaceBatch(@Param("list") List list) {
        return insertBatch(list).replace("INSERT ", "REPLACE ");
    }

    /**
     * 确定字段的数据库名称
     * @param field 字段
     * @return 字段的数据库名称
     */
    private String tableFiled(Field field){
        if (field.isAnnotationPresent(TableField.class)) {
            return field.getAnnotation(TableField.class).value();
        }
        if (field.isAnnotationPresent(TableId.class)){
            String value = field.getAnnotation(TableId.class).value();
            if(StringUtils.isNotBlank(value)){
                return value;
            }
        }
        if(StringUtils.isCamel(field.getName())){
            return StringUtils.camelToUnderline(field.getName());
        }
        return field.getName();
    }
}


//------------------------------------ 内部的SQLBuilder类 end --------------------------------




© 2015 - 2024 Weber Informatics LLC | Privacy Policy