代码

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.diantong.base.mybatis.dao.CommonMapper;
import com.diantong.base.mybatis.pojo.TableColumnsEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author  xiu
 * @date  2021/5/25 19:47
 * @description 校验mybatis plus 和数据库中的字段是否一致,,只是个校验,,哦哦===》其实用jpa也可以
 */
@Configuration
@Slf4j
public class CheckTableInfoConfig implements ApplicationRunner {

    @Autowired(required = false)
    private List<BaseMapper<?>> baseMapperList;
    @Autowired(required = false)
    private CommonMapper commonMapper;

    @Override
    public void run(ApplicationArguments args) {
        if (commonMapper == null || CollectionUtils.isEmpty(baseMapperList)) {
            return;
        }
        StringBuilder allErrorInfo = new StringBuilder();
        for (BaseMapper<?> baseMapper : baseMapperList) {
            StringBuilder errorInfo = new StringBuilder();
            //mapper.class
            Class<?> mapperClass = getMapperGenerics(baseMapper.getClass());
            //entity.class
            Class<?> entityClass = getEntityGenerics(mapperClass);
            if (entityClass == null) {
                log.info("\n**********mapper:{},未找到对应的实体类模型", mapperClass);
                continue;
            }
            //tableInfo信息
            TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
            if (tableInfo == null) {
                allErrorInfo.append("**********实体类:").append(entityClass).append(",在上下文中未找到对应的mybatis模型").append("\n");
                continue;
            }
            //实体类的字段
            List<TableFieldInfo> fieldList = Optional.of(tableInfo).map(TableInfo::getFieldList).orElse(new ArrayList<>());
            //从数据库中查询的表字段
            List<TableColumnsEntity> list;
            try {
                List<JSONObject> data = commonMapper.queryObjects("show columns from " + tableInfo.getTableName());
                list = data.stream().map(t -> TableColumnsEntity.builder()
                        .Field(t.getString("Field"))
                        .Type(t.getString("Type"))
                        .Null(t.getString("Null"))
                        .Key(t.getString("Key"))
                        .Default(t.getString("Default"))
                        .Extra(t.getString("Extra"))
                        .build()).collect(Collectors.toList());
            } catch (Exception e) {
                allErrorInfo.append("**********实体类:").append(entityClass).append(",在数据库中未找到对应的表信息").append("\n");
                allErrorInfo.append(tableInfo.getKeyColumn()).append("\t\t\t").append(tableInfo.getKeyType().getName()).append("\n");
                fieldList.forEach(t -> allErrorInfo.append(t.getColumn()).append("\t\t\t").append(t.getPropertyType().getName()).append("\n"));
                continue;
            }
            List<TableColumnsEntity> finalList = list;
            //循环实体类字段
            boolean haveKeyInEntity = finalList.stream().anyMatch(tempList -> Objects.equals(tableInfo.getKeyColumn(), tempList.getField()));
            if (!haveKeyInEntity) {
                errorInfo.append("表中缺key:\t").append(tableInfo.getKeyColumn()).append("\t\t\t").append(tableInfo.getKeyType().getName()).append("\n");
            }
            fieldList.forEach(tempField -> {
                String column = tempField.getColumn();
                boolean b = finalList.stream().anyMatch(tempList -> Objects.equals(column, tempList.getField()));
                if (!b) {
                    errorInfo.append("表中缺字段:\t").append(column).append("\t\t\t").append(tempField.getPropertyType().getName()).append("\n");
                }
            });
            //循环表中字段
            list.forEach(tempList -> {
                String field = tempList.getField();
                boolean b = fieldList.stream().anyMatch(tempField -> Objects.equals(field, tempField.getColumn()) || Objects.equals(field, tableInfo.getKeyColumn()));
                if (!b) {
                    errorInfo.append("entity中缺字段:\t").append(field).append("\t\t\t").append(tempList.getType()).append("\n");
                }
            });

            if (errorInfo.length() > 0) {
                allErrorInfo.append("**********实体类模型与数据库对应信息错误:").append(entityClass).append("\n");
                allErrorInfo.append(errorInfo);
            }
        }

        if (allErrorInfo.length() > 0) {
            allErrorInfo.insert(0, "\n***********************mybatis plus 和 数据库 校验有误**************************************\n");
            allErrorInfo.append("***********************mybatis plus 和 数据库 校验有误**************************************\n");
            log.error(allErrorInfo.insert(0, "\n").toString());
        } else {
            log.info("\n***********************mybatis plus 和 数据库 校验成功*******************************");
        }
    }

    private Class<?> getMapperGenerics(Class<?> clazz) {
        if (clazz == null) {
            return null;
        }
        try {
            Type[] genericInterfaces = clazz.getGenericInterfaces();
            return Class.forName(genericInterfaces[0].getTypeName());
        } catch (Exception ignored) {
        }
        return null;
    }

    private Class<?> getEntityGenerics(Class<?> clazz) {
        if (clazz == null) {
            return null;
        }
        try {
            Type[] a = clazz.getGenericInterfaces();
            for (Type type : a) {
                if (type instanceof ParameterizedType) {
                    ParameterizedType type1 = (ParameterizedType) type;
                    return (Class<?>) type1.getActualTypeArguments()[0];
                }
            }
        } catch (Exception ignored) {
        }
        return null;
    }

}

效果

在这里插入图片描述

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐