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

sf.querydsl.QueryDSLOrmImpl Maven / Gradle / Ivy

The newest version!
package sf.querydsl;

import com.querydsl.core.QueryMetadata;
import com.querydsl.core.QueryModifiers;
import com.querydsl.core.Tuple;
import com.querydsl.core.support.QueryBaseVistor;
import com.querydsl.core.types.Expression;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.sql.AbstractSQLQuery;
import com.querydsl.sql.ColumnMetadata;
import com.querydsl.sql.Configuration;
import com.querydsl.sql.PrimaryKey;
import com.querydsl.sql.RelationalPath;
import com.querydsl.sql.SQLBindings;
import com.querydsl.sql.SQLQuery;
import com.querydsl.sql.SQLTemplates;
import com.querydsl.sql.dml.AbstractSQLClause;
import com.querydsl.sql.dml.QueryDSLDMLVistor;
import com.querydsl.sql.dml.SQLDeleteClause;
import com.querydsl.sql.dml.SQLInsertClause;
import com.querydsl.sql.dml.SQLMergeClause;
import com.querydsl.sql.dml.SQLUpdateClause;
import sf.common.wrapper.Page;
import sf.core.DBObject;
import sf.database.dao.DBContext;
import sf.database.jdbc.sql.Crud;
import sf.database.jdbc.sql.PageStrategy;
import sf.database.util.DBUtils;
import sf.spring.util.CollectionUtils;
import sf.tools.ArrayUtils;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;

public class QueryDSLOrmImpl implements QueryDSLInf {
    private static QueryDSLOrmImpl instance = new QueryDSLOrmImpl();

    public static QueryDSLOrmImpl getInstance() {
        return instance;
    }

    private QueryDSLOrmImpl() {

    }

    @Override
    public Configuration queryDSLConfiguration(Connection conn, Class... tableClass) {
        SQLTemplates sqlTemplates = QueryDSLDialectUtils.getSQLTemplates(DBUtils.doGetDialect(conn, false).getQueryDslDialect());
        Configuration configuration = new Configuration(sqlTemplates);
        //注入自定义类型
        if (tableClass != null && tableClass.length > 0) {
            for (int i = 0; i < tableClass.length; i++) {
                Class clz = tableClass[i];
                QueryDSL.registerType(clz, configuration);
            }
        }
        return configuration;
    }

    @Override
    public  boolean queryDSLExists(Connection conn, List predicates, Class clz) {
        DBContext context = DBUtils.doGetDBContext(conn);
        SQLRelationalPath table = QueryDSLTables.relationalPathBase(context, clz);
        SQLQuery query = new SQLQuery<>();
        if (CollectionUtils.isNotEmpty(predicates)) {
            query.select(Expressions.ONE/*Wildcard.count*/).from(table).where(predicates.toArray(new Predicate[predicates.size()])).limit(1);
        } else {
            query.select(Expressions.ONE/*Wildcard.count*/).from(table).limit(1);
        }
        setTemplate(conn, query);
        SQLBindings sqlBindings = query.getSQL();
        String sql = sqlBindings.getSQL();
        List values = sqlBindings.getNullFriendlyBindings();
        Byte b = Crud.getInstance().getCrudSql().selectOne(conn, Byte.class, sql, values.toArray());
        return b != null && b > 0;
    }

    @Override
    public  List queryDSLSelectList(Connection conn, AbstractSQLQuery query, Class returnClass) {
        setTemplate(conn, query);
        SQLBindings sqlBindings = query.getSQL();
        String sql = sqlBindings.getSQL();
        List values = sqlBindings.getNullFriendlyBindings();
        Class clz = returnClass;
        if (clz == null) {
            clz = getReturnClz(query);
        }
        return Crud.getInstance().getCrudSql().selectList(conn, clz, sql, values.toArray());
    }

    @Override
    public  Page queryDSLSelectPage(Connection conn, AbstractSQLQuery query, Class returnClass, long start, int limit) {
        setTemplate(conn, query);
        SQLBindings sqlBindings = query.getSQL();
        String countSql = QueryDSL.getCountSql(query);

        List countValues = sqlBindings.getNullFriendlyBindings();
        Object[] countValuesArr = null;
        if (countValues != null) {
            countValuesArr = countValues.toArray();
        } else {
            countValuesArr = ArrayUtils.EMPTY_OBJECT_ARRAY;
        }
        //sqlserver2000 不能设置offset
        if (start >= 0) {
            query.offset(start);
        } else {
            start = 0;
        }
        if (limit >= 0) {
            query.limit(limit);
        } else {
            limit = 0;
        }
        SQLBindings pageListSqlBindings = query.getSQL();
        String pageListSql = pageListSqlBindings.getSQL();
        List pageListValues = pageListSqlBindings.getNullFriendlyBindings();
        Object[] pageListValuesArr = null;
        if (pageListValues != null) {
            pageListValuesArr = pageListValues.toArray();
        } else {
            pageListValuesArr = ArrayUtils.EMPTY_OBJECT_ARRAY;
        }

        //还原offset和limit
        QueryMetadata qm = QueryBaseVistor.getQueryMetadata(query);
        qm.setModifiers(QueryModifiers.EMPTY);

        Class clz = returnClass;
        if (clz == null) {
            clz = getReturnClz(query);
        }
        return Crud.getInstance().getCrudSql().selectPageRaw(conn, start, limit, clz, countSql, countValuesArr, pageListSql, pageListValuesArr, PageStrategy.hasOffsetLimit);
    }


    @Override
    public  T queryDSLSelectOne(Connection conn, AbstractSQLQuery query, Class returnClass) {
        setTemplate(conn, query);
        SQLBindings sqlBindings = query.getSQL();
        String sql = sqlBindings.getSQL();
        List values = sqlBindings.getNullFriendlyBindings();
        Class clz = returnClass;
        if (clz == null) {
            clz = getReturnClz(query);
        }
        return Crud.getInstance().getCrudSql().selectOne(conn, clz, sql, values.toArray());
    }

    @Override
    public  void selectIterator(Connection conn, Consumer> ormIt, AbstractSQLQuery query, Class returnClass) {
        setTemplate(conn, query);
        SQLBindings sqlBindings = query.getSQL();
        String sql = sqlBindings.getSQL();
        List values = sqlBindings.getNullFriendlyBindings();
        Class clz = returnClass;
        if (clz == null) {
            clz = getReturnClz(query);
        }
        Crud.getInstance().getCrudSql().selectIterator(conn, ormIt, clz, false, sql, values.toArray());
    }

    @Override
    public  void selectStream(Connection conn, Consumer> ormStream, AbstractSQLQuery query, Class returnClass) {
        setTemplate(conn, query);
        SQLBindings sqlBindings = query.getSQL();
        String sql = sqlBindings.getSQL();
        List values = sqlBindings.getNullFriendlyBindings();
        Class clz = returnClass;
        if (clz == null) {
            clz = getReturnClz(query);
        }
        Crud.getInstance().getCrudSql().selectStream(conn, ormStream, clz, false, sql, values.toArray());
    }

    @Override
    public int queryDSLInsert(Connection conn, SQLInsertClause insert) {
        RelationalPath base = QueryDSLDMLVistor.getRelationalPath(insert);
        return queryDSLSQLClause(conn, base, insert, null);
    }

    @Override
    public int queryDSLInsert(Connection conn, SQLInsertClause insert, List> keyValues) {
        RelationalPath base = QueryDSLDMLVistor.getRelationalPath(insert);
        return queryDSLSQLClause(conn, base, insert, keyValues);
    }

    @Override
    public int queryDSLUpdate(Connection conn, SQLUpdateClause update) {
        RelationalPath base = QueryDSLDMLVistor.getRelationalPath(update);
        return queryDSLSQLClause(conn, base, update, null);
    }

    @Override
    public int queryDSLDelete(Connection conn, SQLDeleteClause delete) {
        RelationalPath base = QueryDSLDMLVistor.getRelationalPath(delete);
        return queryDSLSQLClause(conn, base, delete, null);
    }

    @Override
    public int queryDSLMerge(Connection conn, SQLMergeClause merge) {
        RelationalPath base = QueryDSLDMLVistor.getRelationalPath(merge);
        return queryDSLSQLClause(conn, base, merge, null);
    }

    @Override
    public int queryDSLMerge(Connection conn, SQLMergeClause merge, List> keyValues) {
        RelationalPath base = QueryDSLDMLVistor.getRelationalPath(merge);
        return queryDSLSQLClause(conn, base, merge, keyValues);
    }

    private int queryDSLSQLClause(Connection conn, RelationalPath base, AbstractSQLClause dml, List> keyValues) {
        setTemplate(conn, dml);
        List pKeys = new ArrayList<>();
//        if (SQLRelationalPath.class.isAssignableFrom(base.getClass())) {
//            SQLRelationalPath path = (SQLRelationalPath) base;
//        }

        PrimaryKey pk = base.getPrimaryKey();
        if (pk != null) {
            List> list = pk.getLocalColumns();
            if (CollectionUtils.isNotEmpty(list)) {
                for (Path p : list) {
                    ColumnMetadata cmd = base.getMetadata(p);
                    if (cmd != null) {
                        pKeys.add(cmd.getName());
                    }
                }
            }
        }

        List sqlBindings = dml.getSQL();
        Map> map = new HashMap<>();
        for (SQLBindings b : sqlBindings) {
            String sql = b.getSQL();
            List bindings = b.getNullFriendlyBindings();
            List objects = map.computeIfAbsent(sql, k -> new ArrayList<>());
            if (CollectionUtils.isNotEmpty(bindings)) {
                objects.add(bindings.toArray());
            }
        }
        int count = 0;
        if (!map.isEmpty()) {
            for (Map.Entry> entry : map.entrySet()) {
                String sql = entry.getKey();
                List objects = entry.getValue();
                int[] counts = Crud.getInstance().getCrudSql().executeBatch(conn, sql, objects, false, 100, pKeys, keyValues);
                for (int i : counts) {
                    count += i;
                }
            }
        }
        return count;
    }

    /**
     * 设置sql模板
     * @param conn
     * @param query
     */
    private void setTemplate(Connection conn, AbstractSQLQuery query) {
        Configuration c = QueryDSL.getConfigurationQuery(query);
        if (c.getTemplates() == SQLTemplates.DEFAULT || c.getTemplates() == null) {
            SQLTemplates sqlTemplates = QueryDSLDialectUtils.getSQLTemplates(DBUtils.doGetDialect(conn, false).getQueryDslDialect());
            if (sqlTemplates != null) {
                c.setTemplates(sqlTemplates);
            } else {
                c.setTemplates(SQLTemplates.DEFAULT);
            }
        }
    }

    public static void setTemplate(Connection conn, AbstractSQLClause query) {
        Configuration c = QueryDSL.getConfigurationDML(query);
        if (c.getTemplates() == SQLTemplates.DEFAULT || c.getTemplates() == null) {
            SQLTemplates sqlTemplates = QueryDSLDialectUtils.getSQLTemplates(DBUtils.doGetDialect(conn, false).getQueryDslDialect());
            if (sqlTemplates != null) {
                c.setTemplates(sqlTemplates);
            } else {
                c.setTemplates(SQLTemplates.DEFAULT);
            }
        }
    }

    /**
     * 获取返回值的对象,该方法存在bug,在某些特殊方法下存在,返回值为空的情况
     * @param query
     * @param 
     * @return
     */
    public static  Class getReturnClz(AbstractSQLQuery query) {
        //在某些特殊方法下存在,expression为空
        //使用查询全部字段存在该问题(XXX.all())
        Expression expression = query.getMetadata().getProjection();
        Class type = expression.getType();
        Class clz = Map.class;
        if (type != null && !Tuple.class.isAssignableFrom(type)) {
            clz = type;
        }
        return (Class) clz;
    }
}