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

org.zodiac.mybatisplus.binding.parser.ParserCache Maven / Gradle / Ivy

There is a newer version: 1.6.8
Show newest version
package org.zodiac.mybatisplus.binding.parser;

import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.lang.NonNull;
import org.zodiac.commons.util.ArrayUtil;
import org.zodiac.commons.util.BeanUtil;
import org.zodiac.commons.util.Colls;
import org.zodiac.core.data.annotation.ProtectField;
import org.zodiac.core.exception.IllegalUsageException;
import org.zodiac.mybatisplus.binding.annotation.*;
import org.zodiac.mybatisplus.binding.cache.BindingCacheManager;
import org.zodiac.mybatisplus.binding.query.BindQuery;
import org.zodiac.mybatisplus.binding.query.dynamic.AnnoJoiner;
import org.zodiac.sdk.toolkit.util.lang.StrUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;

/**
 * 对象中的绑定注解 缓存管理类。
 * 
 */
@SuppressWarnings({"rawtypes"})
public class ParserCache {

    private static final Logger log = LoggerFactory.getLogger(ParserCache.class);

    /**
     * VO类-绑定注解缓存
     */
    private static final Map, BindAnnotationGroup> allVoBindAnnotationCacheMap = new ConcurrentHashMap<>();
    /**
     * dto类-BindQuery注解的缓存
     */
    private static final Map> dtoClassBindQueryCacheMap = new ConcurrentHashMap<>();
    /**
     * 保护字段缓存
     */
    private static final Map> PROTECT_FIELD_MAP = new ConcurrentHashMap<>();

    /**
     * 用于查询注解是否是Bind相关注解
     */
    private static final Set> BIND_ANNOTATION_SET = new HashSet<>(Arrays.asList(BindDict.class,
        BindField.class, BindFieldList.class, BindEntity.class, BindEntityList.class, BindCount.class));

    private ParserCache() {
        super();
    }

    /**
     * 获取指定class对应的Bind相关注解。
     * 
     * @param voClass vo类型对象
     * @return 绑定注解的归类分组对象
     */
    public static BindAnnotationGroup getBindAnnotationGroup(Class voClass) {
        return allVoBindAnnotationCacheMap.computeIfAbsent(voClass, k -> {
            /*获取注解并缓存*/
            BindAnnotationGroup group = new BindAnnotationGroup();
            /*获取当前VO的所有字段*/
            List fields = BeanUtil.extractAllFields(voClass);
            if (Colls.notEmptyColl(fields)) {
                /*遍历属性*/
                for (Field field : fields) {
                    /*获取当前字段所有注解*/
                    Annotation[] annotations = field.getDeclaredAnnotations();
                    if (ArrayUtil.emptyArray(annotations)) {
                        continue;
                    }
                    /*字段名称*/
                    String fieldName = field.getName();
                    /*字段类型*/
                    Class setterObjClazz = field.getType();
                    /*如果是集合,获取其泛型参数class*/
                    if (setterObjClazz.equals(java.util.List.class)
                        || setterObjClazz.equals(java.util.Collection.class)) {
                        Type genericType = field.getGenericType();
                        if (genericType instanceof ParameterizedType) {
                            ParameterizedType pt = (ParameterizedType)genericType;
                            setterObjClazz = (Class)pt.getActualTypeArguments()[0];
                        }
                    }
                    for (Annotation annotation : annotations) {
                        /*是bind相关注解则添加*/
                        if (BIND_ANNOTATION_SET.contains(annotation.annotationType())) {
                            group.addBindAnnotation(fieldName, setterObjClazz, annotation);
                        }
                    }
                }
            }
            /*返回归类后的注解对象*/
            return group;
        });
    }

    /**
     * 取得“删除”列。
     * 
     * @param table 表名
     * @return 列名
     */
    public static String getDeletedColumn(String table) {
        PropInfo propInfo = BindingCacheManager.getPropInfoByTable(table);
        if (propInfo != null) {
            return propInfo.getDeletedColumn();
        }
        log.debug("未能识别到逻辑删除字段, table={}", table);
        return null;
    }

    /**
     * 获取entity对应的表名。
     * 
     * @param entityClass 实体类型对象
     * @return 表名称
     */
    public static String getEntityTableName(Class entityClass) {
        EntityInfoCache entityInfoCache = BindingCacheManager.getEntityInfoByClass(entityClass);
        if (entityInfoCache != null) {
            return entityInfoCache.getTableName();
        } else {
            TableName tableNameAnno = AnnotationUtils.findAnnotation(entityClass, TableName.class);
            if (tableNameAnno != null && StrUtil.isNotBlank(tableNameAnno.value())) {
                return tableNameAnno.value();
            } else {
                return StrUtil.toSnakeCase(entityClass.getSimpleName());
            }
        }
    }

    /**
     * 根据类的entity类名获取EntityClass(已废弃) 请调用{@link BindingCacheManager#getEntityClassBySimpleName(String)}}。
     * 
     * @param className 类名
     * @return 类型对象
     */
    @Deprecated
    public static Class getEntityClassByClassName(String className) {
        return BindingCacheManager.getEntityClassBySimpleName(className);
    }

    /**
     * 根据entity类获取mapper实例。
     * 
     * @param entityClass 实体类型
     * @return {@link BaseMapper}对象
     */
    public static BaseMapper getMapperInstance(Class entityClass) {
        BaseMapper mapper = BindingCacheManager.getMapperByClass(entityClass);
        if (mapper == null) {
            throw new IllegalUsageException("未找到 " + entityClass.getName() + " 的Mapper定义!");
        }
        return mapper;
    }

    /**
     * 当前DTO是否有Join绑定。
     * 
     * @param  DTO类型
     * @param dto dto对象
     * @param fieldNameSet 有值属性集合
     * @return 是否连接表
     */
    public static  boolean hasJoinTable(DTO dto, Collection fieldNameSet) {
        List annoList = getBindQueryAnnos(dto.getClass());
        if (Colls.notEmptyColl(annoList)) {
            for (AnnoJoiner anno : annoList) {
                if (StrUtil.isNotBlank(anno.getJoin()) && Colls.containsInstance(fieldNameSet, anno.getFieldName())) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 获取dto类中定义的BindQuery注解。
     * 
     * @param dtoClass DTO类型
     * @return 注解连接器列表
     */
    public static List getBindQueryAnnos(Class dtoClass) {
        String dtoClassName = dtoClass.getName();
        if (dtoClassBindQueryCacheMap.containsKey(dtoClassName)) {
            return dtoClassBindQueryCacheMap.get(dtoClassName);
        }
        /*初始化。*/
        List annos = new ArrayList<>();
        AtomicInteger index = new AtomicInteger(1);
        Map joinOn2Alias = new HashMap<>(8);
        /*构建AnnoJoiner。*/
        BiConsumer buildAnnoJoiner = (field, query) -> {
            AnnoJoiner annoJoiner = new AnnoJoiner(field, query);
            /*关联对象,设置别名。*/
            if (StrUtil.isNotBlank(annoJoiner.getJoin())) {
                String key = annoJoiner.getJoin() + ":" + annoJoiner.getCondition();
                String alias = joinOn2Alias.get(key);
                if (alias == null) {
                    alias = "r" + index.getAndIncrement();
                    annoJoiner.setAlias(alias);
                    joinOn2Alias.put(key, alias);
                } else {
                    annoJoiner.setAlias(alias);
                }
                annoJoiner.parse();
            }
            annos.add(annoJoiner);
        };
        for (Field field : BeanUtil.extractFields(dtoClass, BindQuery.class)) {
            BindQuery query = field.getAnnotation(BindQuery.class);
            /*不可能为null。*/
            if (query.ignore()) {
                continue;
            }
            buildAnnoJoiner.accept(field, query);
        }
        for (Field field : BeanUtil.extractFields(dtoClass, BindQuery.List.class)) {
            BindQuery.List queryList = field.getAnnotation(BindQuery.List.class);
            for (BindQuery bindQuery : queryList.value()) {
                buildAnnoJoiner.accept(field, bindQuery);
            }
        }
        dtoClassBindQueryCacheMap.put(dtoClassName, annos);
        return annos;
    }

    /**
     * 获取注解joiner。
     * 
     * @param dtoClass DTO类型
     * @param fieldNames 字段名列表
     * @return 注解连接器列表
     */
    public static List getAnnoJoiners(Class dtoClass, Collection fieldNames) {
        List annoList = getBindQueryAnnos(dtoClass);
        /*不过滤 返回全部*/
        if (fieldNames == null) {
            return annoList;
        }
        /*过滤*/
        if (Colls.notEmptyColl(annoList)) {
            List matchedAnnoList = new ArrayList<>();
            for (AnnoJoiner anno : annoList) {
                if (fieldNames.contains(anno.getFieldName())) {
                    matchedAnnoList.add(anno);
                }
            }
            return matchedAnnoList;
        }
        return Collections.emptyList();
    }

    /**
     * 获取该类保护字段属性名列表。
     *
     * @param clazz 类型
     * @return 属性名列表
     */
    @NonNull
    public static List getProtectFieldList(@NonNull Class clazz) {
        return PROTECT_FIELD_MAP.computeIfAbsent(clazz.getName(), k -> {
            List protectFieldList = new ArrayList<>(4);
            for (Field field : BeanUtil.extractFields(clazz, ProtectField.class)) {
                if (!field.getType().isAssignableFrom(String.class)) {
                    log.error("`@ProtectField` 仅支持 String 类型字段。");
                    continue;
                }
                protectFieldList.add(field.getName());
            }
            return protectFieldList.isEmpty() ? Collections.emptyList() : protectFieldList;
        });
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy