Search in sources :

Example 1 with DynamicJoinQueryWrapper

use of com.diboot.core.binding.query.dynamic.DynamicJoinQueryWrapper in project diboot by dibo-software.

the class JoinsBinder method executeJoinQuery.

/**
 * 关联查询(分页)
 * @param queryWrapper 调用QueryBuilder.to*QueryWrapper得到的实例
 * @param entityClazz 返回结果entity/vo类
 * @param pagination 分页
 * @return
 * @throws Exception
 */
private static <DTO, E> List<E> executeJoinQuery(QueryWrapper<DTO> queryWrapper, Class<E> entityClazz, Pagination pagination, boolean limit1) {
    // 非动态查询,走BaseService
    if (queryWrapper instanceof DynamicJoinQueryWrapper == false) {
        IService iService = ContextHelper.getIServiceByEntity(entityClazz);
        if (iService != null) {
            return ServiceAdaptor.queryList(iService, (QueryWrapper) queryWrapper, pagination, entityClazz);
        } else {
            throw new InvalidUsageException("单表查询对象无BaseService/IService实现: " + entityClazz.getSimpleName());
        }
    }
    long begin = System.currentTimeMillis();
    // 转换为queryWrapper
    DynamicJoinQueryWrapper dynamicJoinWrapper = (DynamicJoinQueryWrapper) queryWrapper;
    dynamicJoinWrapper.setMainEntityClass(entityClazz);
    List<Map<String, Object>> mapList = null;
    if (pagination == null) {
        if (limit1) {
            Page page = new Page<>(1, 1);
            page.setSearchCount(false);
            IPage<Map<String, Object>> pageResult = getDynamicQueryMapper().queryForListWithPage(page, dynamicJoinWrapper);
            mapList = pageResult.getRecords();
        } else {
            mapList = getDynamicQueryMapper().queryForList(dynamicJoinWrapper);
        }
    } else {
        // 格式化orderBy
        formatOrderBy(dynamicJoinWrapper, entityClazz, pagination);
        IPage<Map<String, Object>> pageResult = getDynamicQueryMapper().queryForListWithPage(pagination.toPage(), dynamicJoinWrapper);
        pagination.setTotalCount(pageResult.getTotal());
        mapList = pageResult.getRecords();
    }
    long ms = (System.currentTimeMillis() - begin);
    if (ms > 5000) {
        log.warn("{} 动态Join查询执行耗时 {} ms,建议优化", dynamicJoinWrapper.getDtoClass().getSimpleName(), ms);
    }
    if (V.isEmpty(mapList)) {
        return Collections.emptyList();
    }
    if (mapList.size() > BaseConfig.getBatchSize()) {
        log.warn("{} 动态Join查询记录数过大( {} 条), 建议优化", dynamicJoinWrapper.getDtoClass().getSimpleName(), mapList.size());
    }
    // 转换查询结果
    List<E> entityList = new ArrayList<>();
    for (Map<String, Object> colValueMap : mapList) {
        Map<String, Object> fieldValueMap = new HashMap<>();
        // 格式化map
        for (Map.Entry<String, Object> entry : colValueMap.entrySet()) {
            String fieldName = S.toLowerCaseCamel(entry.getKey());
            // 如果是布尔类型,检查entity中的定义是Boolean/boolean
            if (entry.getValue() instanceof Boolean && S.startsWithIgnoreCase(entry.getKey(), "is_")) {
                // 检查有is前缀的Boolean类型
                Field boolType = BeanUtils.extractField(entityClazz, fieldName);
                if (boolType == null) {
                    // 检查无is前缀的boolean类型
                    String tempFieldName = S.toLowerCaseCamel(S.substringAfter(entry.getKey(), "_"));
                    boolType = BeanUtils.extractField(entityClazz, tempFieldName);
                    if (boolType != null) {
                        fieldName = tempFieldName;
                    }
                }
            }
            fieldValueMap.put(fieldName, entry.getValue());
        }
        // 绑定map到entity
        try {
            E entityInst = entityClazz.newInstance();
            BeanUtils.bindProperties(entityInst, fieldValueMap);
            if (ENABLE_DATA_PROTECT) {
                ParserCache.getFieldEncryptorMap(entityClazz).forEach((k, v) -> {
                    String value = BeanUtils.getStringProperty(entityInst, k);
                    BeanUtils.setProperty(entityInst, k, value == null ? null : v.decrypt(value));
                });
            }
            entityList.add(entityInst);
        } catch (Exception e) {
            log.warn("new实例并绑定属性值异常", e);
        }
    }
    return entityList;
}
Also used : Page(com.baomidou.mybatisplus.extension.plugins.pagination.Page) IPage(com.baomidou.mybatisplus.core.metadata.IPage) DynamicJoinQueryWrapper(com.diboot.core.binding.query.dynamic.DynamicJoinQueryWrapper) InvalidUsageException(com.diboot.core.exception.InvalidUsageException) Field(java.lang.reflect.Field) IService(com.baomidou.mybatisplus.extension.service.IService) InvalidUsageException(com.diboot.core.exception.InvalidUsageException)

Example 2 with DynamicJoinQueryWrapper

use of com.diboot.core.binding.query.dynamic.DynamicJoinQueryWrapper in project diboot by dibo-software.

the class QueryBuilder method dtoToWrapper.

/**
 * 转换具体实现
 *
 * @param dto
 * @return
 */
private static <DTO> QueryWrapper<?> dtoToWrapper(DTO dto, Collection<String> fields) {
    QueryWrapper<?> wrapper;
    // 转换
    LinkedHashMap<String, FieldAndValue> fieldValuesMap = extractNotNullValues(dto, fields);
    if (V.isEmpty(fieldValuesMap)) {
        return new QueryWrapper<>();
    }
    // 只解析有值的
    fields = fieldValuesMap.keySet();
    // 是否有join联表查询
    boolean hasJoinTable = ParserCache.hasJoinTable(dto, fields);
    if (hasJoinTable) {
        wrapper = new DynamicJoinQueryWrapper<>(dto.getClass(), fields);
    } else {
        wrapper = new ExtQueryWrapper<>();
    }
    // 构建 ColumnName
    List<AnnoJoiner> annoJoinerList = ParserCache.getBindQueryAnnos(dto.getClass());
    BiFunction<BindQuery, Field, String> buildColumnName = (bindQuery, field) -> {
        if (bindQuery != null) {
            String key = field.getName() + bindQuery;
            for (AnnoJoiner annoJoiner : annoJoinerList) {
                if (key.equals(annoJoiner.getKey())) {
                    if (V.notEmpty(annoJoiner.getJoin())) {
                        // 获取注解Table
                        return annoJoiner.getAlias() + "." + annoJoiner.getColumnName();
                    } else {
                        return (hasJoinTable ? "self." : "") + annoJoiner.getColumnName();
                    }
                }
            }
        }
        return (hasJoinTable ? "self." : "") + BeanUtils.getColumnName(field);
    };
    // 忽略空字符串"",空集合等
    BiFunction<Object, BindQuery, Boolean> ignoreEmpty = (value, bindQuery) -> bindQuery != null && // 忽略空字符串"",空集合等
    bindQuery.strategy().equals(Strategy.IGNORE_EMPTY) && (// 字符串""
    value instanceof String && S.isEmpty((String) value) || // 空集合
    (value instanceof Collection && ((Collection<?>) value).size() == 0));
    // 查找加密策略
    BiFunction<BindQuery, String, IEncryptStrategy> findEncryptStrategy = (bindQuery, defFieldName) -> {
        if (ENABLE_DATA_PROTECT) {
            Class<?> clazz = bindQuery == null || bindQuery.entity() == NullType.class ? dto.getClass() : bindQuery.entity();
            String fieldName = bindQuery == null || S.isEmpty(bindQuery.field()) ? defFieldName : bindQuery.field();
            return ParserCache.getFieldEncryptorMap(clazz).get(fieldName);
        }
        return null;
    };
    // 构建QueryWrapper
    for (Map.Entry<String, FieldAndValue> entry : fieldValuesMap.entrySet()) {
        FieldAndValue fieldAndValue = entry.getValue();
        Field field = fieldAndValue.getField();
        // 忽略注解 @TableField(exist = false) 的字段
        TableField tableField = field.getAnnotation(TableField.class);
        if (tableField != null && !tableField.exist()) {
            continue;
        }
        // 忽略字段
        BindQuery query = field.getAnnotation(BindQuery.class);
        if (query != null && query.ignore()) {
            continue;
        }
        BindQuery.List queryList = field.getAnnotation(BindQuery.List.class);
        Object value = fieldAndValue.getValue();
        // 构建Query
        if (queryList != null) {
            wrapper.and(queryWrapper -> {
                for (BindQuery bindQuery : queryList.value()) {
                    if (ignoreEmpty.apply(value, bindQuery)) {
                        continue;
                    }
                    IEncryptStrategy encryptor = findEncryptStrategy.apply(bindQuery, entry.getKey());
                    Comparison comparison = encryptor == null ? bindQuery.comparison() : Comparison.EQ;
                    String columnName = buildColumnName.apply(bindQuery, field);
                    buildQuery(queryWrapper.or(), comparison, columnName, encryptor == null ? value : encryptor.encrypt(value.toString()));
                }
            });
        } else {
            if (ignoreEmpty.apply(value, query)) {
                continue;
            }
            IEncryptStrategy encryptor = findEncryptStrategy.apply(query, entry.getKey());
            Comparison comparison = query != null && encryptor == null ? query.comparison() : Comparison.EQ;
            String columnName = buildColumnName.apply(query, field);
            buildQuery(wrapper, comparison, columnName, encryptor == null ? value : encryptor.encrypt(value.toString()));
        }
    }
    return wrapper;
}
Also used : AnnoJoiner(com.diboot.core.binding.query.dynamic.AnnoJoiner) Comparison(com.diboot.core.binding.query.Comparison) java.util(java.util) BiFunction(java.util.function.BiFunction) Cons(com.diboot.core.config.Cons) LoggerFactory(org.slf4j.LoggerFactory) ExtQueryWrapper(com.diboot.core.binding.query.dynamic.ExtQueryWrapper) LambdaQueryWrapper(com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper) PropertiesUtils(com.diboot.core.util.PropertiesUtils) Method(java.lang.reflect.Method) BeanUtils(com.diboot.core.util.BeanUtils) QueryWrapper(com.baomidou.mybatisplus.core.conditions.query.QueryWrapper) Logger(org.slf4j.Logger) NullType(javax.lang.model.type.NullType) TableLogic(com.baomidou.mybatisplus.annotation.TableLogic) Field(java.lang.reflect.Field) TableField(com.baomidou.mybatisplus.annotation.TableField) IEncryptStrategy(com.diboot.core.data.encrypt.IEncryptStrategy) InvocationTargetException(java.lang.reflect.InvocationTargetException) DynamicJoinQueryWrapper(com.diboot.core.binding.query.dynamic.DynamicJoinQueryWrapper) S(com.diboot.core.util.S) V(com.diboot.core.util.V) Modifier(java.lang.reflect.Modifier) ISqlSegment(com.baomidou.mybatisplus.core.conditions.ISqlSegment) NormalSegmentList(com.baomidou.mybatisplus.core.conditions.segments.NormalSegmentList) BindQuery(com.diboot.core.binding.query.BindQuery) ParserCache(com.diboot.core.binding.parser.ParserCache) Strategy(com.diboot.core.binding.query.Strategy) Field(java.lang.reflect.Field) TableField(com.baomidou.mybatisplus.annotation.TableField) BindQuery(com.diboot.core.binding.query.BindQuery) Comparison(com.diboot.core.binding.query.Comparison) IEncryptStrategy(com.diboot.core.data.encrypt.IEncryptStrategy) ExtQueryWrapper(com.diboot.core.binding.query.dynamic.ExtQueryWrapper) LambdaQueryWrapper(com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper) QueryWrapper(com.baomidou.mybatisplus.core.conditions.query.QueryWrapper) DynamicJoinQueryWrapper(com.diboot.core.binding.query.dynamic.DynamicJoinQueryWrapper) TableField(com.baomidou.mybatisplus.annotation.TableField) AnnoJoiner(com.diboot.core.binding.query.dynamic.AnnoJoiner) NullType(javax.lang.model.type.NullType)

Aggregations

DynamicJoinQueryWrapper (com.diboot.core.binding.query.dynamic.DynamicJoinQueryWrapper)2 Field (java.lang.reflect.Field)2 TableField (com.baomidou.mybatisplus.annotation.TableField)1 TableLogic (com.baomidou.mybatisplus.annotation.TableLogic)1 ISqlSegment (com.baomidou.mybatisplus.core.conditions.ISqlSegment)1 LambdaQueryWrapper (com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper)1 QueryWrapper (com.baomidou.mybatisplus.core.conditions.query.QueryWrapper)1 NormalSegmentList (com.baomidou.mybatisplus.core.conditions.segments.NormalSegmentList)1 IPage (com.baomidou.mybatisplus.core.metadata.IPage)1 Page (com.baomidou.mybatisplus.extension.plugins.pagination.Page)1 IService (com.baomidou.mybatisplus.extension.service.IService)1 ParserCache (com.diboot.core.binding.parser.ParserCache)1 BindQuery (com.diboot.core.binding.query.BindQuery)1 Comparison (com.diboot.core.binding.query.Comparison)1 Strategy (com.diboot.core.binding.query.Strategy)1 AnnoJoiner (com.diboot.core.binding.query.dynamic.AnnoJoiner)1 ExtQueryWrapper (com.diboot.core.binding.query.dynamic.ExtQueryWrapper)1 Cons (com.diboot.core.config.Cons)1 IEncryptStrategy (com.diboot.core.data.encrypt.IEncryptStrategy)1 InvalidUsageException (com.diboot.core.exception.InvalidUsageException)1