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

cn.tenfell.plugins.dbgenerate.utils.DocUtils Maven / Gradle / Ivy

package cn.tenfell.plugins.dbgenerate.utils;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ModifierUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.tenfell.plugins.dbgenerate.annotation.Table;
import cn.tenfell.plugins.dbgenerate.annotation.TableColumn;
import cn.tenfell.plugins.dbgenerate.annotation.TableNoExist;
import cn.tenfell.plugins.dbgenerate.config.DbGenerateProperties;
import cn.tenfell.plugins.dbgenerate.entity.ColumnProp;
import cn.tenfell.plugins.dbgenerate.entity.DefaultAnnotation;
import cn.tenfell.plugins.dbgenerate.entity.TableColumnProp;
import cn.tenfell.plugins.dbgenerate.entity.TableProp;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.dialect.Database;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.dialect.spi.DatabaseMetaDataDialectResolutionInfoAdapter;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.type.AbstractSingleColumnStandardBasicType;
import org.hibernate.type.StringType;

import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.Types;
import java.util.*;

/**
 * 文档生成工具类
 * @author fs
 */
@UtilityClass
@Slf4j
public class DocUtils {
    public static String time;
    public final static DbGenerateProperties dbGenerateProperties = new DbGenerateProperties();
    private static Map> allTypes;
    private static Map allDbCodes;
    public static Dialect sqlDialect;
    public static DataSource dataSource;
    public static Map allDataByDb = new HashMap<>();
    public static Map allDataByBeans = new HashMap<>();
    public static List> allKeys = new ArrayList<>();
    public void init(DataSource ds){
        Assert.notNull(dbGenerateProperties.getBeanPackages(),"当前没有配置实体扫描路径");
        dataSource = ds;
        Connection connection = null;
        try{
            connection = dataSource.getConnection();
        }catch (Exception e){

        }
        Assert.notNull(connection,"无法获取数据库连接信息");
        DatabaseMetaData metaData = null;
        try{
            metaData = connection.getMetaData();
        }catch (Exception e){

        }
        Assert.notNull(connection,"无法获取连接池信息");
        Assert.notNull(metaData,"无法获取metaData");
        try{
            SqlUtils.catalog =connection.getCatalog();
        }catch (Exception e){
            Assert.isTrue(false,"无法读取catalog");
        }
        try{
            SqlUtils.schema =connection.getSchema();
        }catch (Exception e){
            Assert.isTrue(false,"无法读取schema");
        }
        DialectResolutionInfo info = new DatabaseMetaDataDialectResolutionInfoAdapter(metaData);
        Dialect dialect = null;
        for ( Database database : Database.values() ) {
            dialect = database.resolveDialect( info );
            if ( dialect != null ) {
                break;
            }
        }
        Assert.notNull(dialect,"暂时无法支持你的数据库");
        sqlDialect = dialect;
        ReflectUtil.invoke(sqlDialect,"registerColumnType",Types.DOUBLE,"double($p,$s)");
        ReflectUtil.invoke(sqlDialect,"registerColumnType",Types.FLOAT,"float($p,$s)");
        updateData();
        DocUtils.time = DateUtil.now();
    }
    public void updateData(){
        allDataByDb = null;
        allDataByBeans=null;
        allKeys = null;
        /**
         * 从实体获取所有属性
         */
        createBeanData();
        /**
         *从数据库获取所有属性
         */
        createDbData();
        /**
         * 进行数据组合
         */
        createKeys();
    }
    private static void createKeys(){
        allKeys = new ArrayList<>();
        Map> tempAllKeys = new HashMap<>();
        List beans = new ArrayList<>(allDataByBeans.values());
        List bds = new ArrayList<>(allDataByDb.values());
        beans.addAll(bds);
        for(TableColumnProp one:beans){
            TableProp table = one.getTable();
            Set colSets = tempAllKeys.get(table.getTableName());
            if(colSets == null){
                colSets = new HashSet<>();
                tempAllKeys.put(table.getTableName(),colSets);
            }
            Map columnPropMap = one.getColumns();
            List columnProps = new ArrayList<>(columnPropMap.values());
            for(ColumnProp columnProp:columnProps){
                colSets.add(columnProp.getColumn());
            }
        }
        Set keys = tempAllKeys.keySet();
        for(String key:keys){
            Map map = new HashMap<>();
            map.put("table",key);
            List columns = new ArrayList<>();
            columns.addAll(tempAllKeys.get(key));
            columns.sort(new Comparator() {
                @Override
                public int compare(String o1, String o2) {
                    return o1.compareTo(o2);
                }
            });
            map.put("columns",columns);
            allKeys.add(map);
            if(allDataByDb.get(key) == null){
                TableColumnProp tableColumnProp = new TableColumnProp();
                tableColumnProp.setTable(new TableProp());
                tableColumnProp.setColumns(new HashMap());
                allDataByDb.put(key,tableColumnProp);
            }
            if(allDataByBeans.get(key) == null){
                TableColumnProp tableColumnProp = new TableColumnProp();
                tableColumnProp.setTable(new TableProp());
                tableColumnProp.setColumns(new HashMap());
                allDataByBeans.put(key,tableColumnProp);
            }
        }
        allKeys.sort(new Comparator>() {
            @Override
            public int compare(Map o1, Map o2) {
                String t1 = (String)o1.get("table");
                String t2 = (String)o2.get("table");
                return t1.compareTo(t2);
            }
        });
    }
    private static void createBeanData(){
        allDataByBeans = new HashMap<>();
        Set clazzs = new HashSet<>();
        for(String pka:dbGenerateProperties.getBeanPackages()){
            clazzs.addAll(ClassUtil.scanPackage(pka));
        }
        for(Class clazz:clazzs){
            TableNoExist tne = (TableNoExist)clazz.getAnnotation(TableNoExist.class);
            if(tne != null){
                continue;
            }
            Table taba = (Table)clazz.getAnnotation(Table.class);
            if(taba == null){
                taba = DefaultAnnotation.class.getAnnotation(Table.class);
            }
            TableColumnProp tableColumnProp = new TableColumnProp();
            TableProp table = new TableProp();
            table.setComment(taba.comment());
            if(StrUtil.isNotBlank(taba.tableName())){
                table.setTableName(taba.tableName());
            }else{
                table.setTableName(StrUtil.toUnderlineCase(clazz.getSimpleName()));
            }
            tableColumnProp.setTable(table);
            Field[] fields = ReflectUtil.getFields(clazz);
            Map columns = new HashMap<>();
            for(Field field:fields){
                if(ModifierUtil.isStatic(field)){
                    continue;
                }
                TableNoExist tfne = field.getAnnotation(TableNoExist.class);
                if(tfne != null){
                    continue;
                }
                Type javaType = field.getGenericType();
                if(javaType == null || !(javaType instanceof Class)){
                    continue;
                }
                TableColumn tabCol = field.getAnnotation(TableColumn.class);
                if(tabCol == null){
                    tabCol = DefaultAnnotation.tableColumnMap().get(javaType.getTypeName());
                }
                if(tabCol == null){
                    continue;
                }
                Integer code = tabCol.type().getVendorTypeNumber();
                String type = null;
                if(code == Types.OTHER){
                    if(javaType == String.class){
                        type = sqlDialect.getHibernateTypeName(Types.VARCHAR,tabCol.length(),tabCol.length(),tabCol.decimal());
                    }else{
                        type = getHibernateTypeByClass((Class)javaType);
                    }
                }else{
                    type = sqlDialect.getHibernateTypeName(code,tabCol.length(),tabCol.length(),tabCol.decimal());
                }
                if(StrUtil.isBlank(type)){
                    continue;
                }
                ColumnProp columnProp = new ColumnProp();
                columnProp.setPrimaryIs(tabCol.isprimary());
                columnProp.setNullIs(tabCol.isnull());
                columnProp.setDecimal(Convert.toInt(tabCol.decimal()));
                columnProp.setLength(Convert.toInt(tabCol.length()));
                if(StrUtil.isNotBlank(tabCol.column())){
                    columnProp.setColumn(tabCol.column());
                }else{
                    columnProp.setColumn(StrUtil.toUnderlineCase(field.getName()));
                }
                columnProp.setComment(tabCol.comment());
                columnProp.setType(type);
                columns.put(columnProp.getColumn(),columnProp);
            }
            tableColumnProp.setColumns(columns);
            allDataByBeans.put(table.getTableName(),tableColumnProp);
        }
    }
    public static void createDbData(){
        allDataByDb = new HashMap<>();
        try{
            Connection connection=dataSource.getConnection();
            String catalog = connection.getCatalog();
            String schema = connection.getSchema();
            final DatabaseMetaData databaseMetaData = connection.getMetaData();
            String[] types = new String[]{"TABLE"};
            ResultSet resultSet =  databaseMetaData.getTables(catalog,schema,"%",types);
            List list = new ArrayList<>();
            while (resultSet.next()) {
                String name = resultSet.getString( "TABLE_NAME" );
                String comment = resultSet.getString("REMARKS");
                TableColumnProp tableColumnProp = new TableColumnProp();
                TableProp tableProp = new TableProp();
                tableProp.setTableName(name);
                tableProp.setComment(comment);
                tableColumnProp.setTable(tableProp);
                list.add(tableColumnProp);
            }
            resultSet.close();
            for(TableColumnProp tableColumnProp:list){
                ResultSet colRes = databaseMetaData.getColumns(catalog,schema,tableColumnProp.getTable().getTableName(),"%");
                Map columns = new HashMap<>();
                tableColumnProp.setColumns(columns);
                allDataByDb.put(tableColumnProp.getTable().getTableName(),tableColumnProp);
                while(colRes.next()){
                    Integer code = colRes.getInt( "DATA_TYPE" );
                    int length = colRes.getInt( "COLUMN_SIZE" );
                    int scale = colRes.getInt( "DECIMAL_DIGITS" );
                    String type = null;
                    try{
                        type = sqlDialect.getHibernateTypeName(code,length,length,scale);
                    }catch (Exception e){
                        System.out.println("当前类型不受支持:"+code);
                    }
                    if(StrUtil.isBlank(type)){
                        System.out.println("当前类型不受支持:"+code);
                        continue;
                    }
                    if(getAllTypes().get(type) == null){
                        System.out.println("当前类型不受支持:"+code);
                        continue;
                    }
                    ColumnProp column = new ColumnProp();
                    column.setColumn(colRes.getString( "COLUMN_NAME" ));
                    column.setType(type);
                    column.setLength(length);
                    column.setComment(colRes.getString("REMARKS"));
                    column.setDecimal(scale);
                    column.setNullIs(StrUtil.equals(colRes.getString( "IS_NULLABLE" ).toUpperCase(),"YES"));
                    column.setPrimaryIs(false);
                    columns.put(column.getColumn(),column);
                }
                colRes.close();
                ResultSet pkRes=databaseMetaData.getPrimaryKeys(catalog,schema,tableColumnProp.getTable().getTableName());
                while(pkRes.next()){
                    Collection tmpColumns = columns.values();
                    for(ColumnProp columnProp:tmpColumns){
                        String columnName = pkRes.getString("COLUMN_NAME");
                        if(!StrUtil.equals(columnProp.getColumn(),columnName)){
                           continue;
                        }
                        columnProp.setPrimaryIs(true);
                    }
                }
                pkRes.close();
            }
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
    private static String getHibernateTypeByClass(Class clazz){
        String type = null;
        Collection> list = getAllTypes().values();
        for(Map map:list){
            Class one = (Class)map.get("javaClass");
            if(ClassUtil.isAssignable(clazz,one) && ClassUtil.isAssignable(one,clazz)){
                type = (String)map.get("name");
                break;
            }
        }
        return type;
    }
    public static Map> getAllTypes(){
        if(allTypes != null){
            return allTypes;
        }
        Set> sets = ClassUtil.scanPackageBySuper("org.hibernate.type", AbstractSingleColumnStandardBasicType.class);
        allTypes = new HashMap<>();
        for(Class one:sets){
            String name = null;
            Object obj = null;
            try{
                obj = ReflectUtil.newInstanceIfPossible(one);
                name = ReflectUtil.invoke(obj,"getName");
            }catch (Exception e){

            }
            if(name == null){
                continue;
            }
            java.lang.reflect.Type type = one.getGenericSuperclass();
            if(!(type instanceof ParameterizedType)){
                continue;
            }
            ParameterizedType pt = (ParameterizedType)type;
            java.lang.reflect.Type[] children = pt.getActualTypeArguments();
            if(children.length != 1){
                continue;
            }
            Type child = children[0];
            if(!(child instanceof Class)){
                continue;
            }
            Class the = (Class)child;
            Map temp = new HashMap<>();
            temp.put("hibernateClass",one);
            temp.put("hibernateObj",obj);
            temp.put("javaClass",the);
            temp.put("name",name);
            allTypes.put(name,temp);
        }
        return allTypes;
    }
    public static org.hibernate.type.Type getTypeByHibernateName(String name){
       Collection> list = getAllTypes().values();
        org.hibernate.type.Type type = null;
       for(Map one:list){
           if(StrUtil.equals(Convert.toStr(one.get("name")),name)){
               type = (org.hibernate.type.Type)(one.get("hibernateObj"));
               break;
           }
       }
       if(type == null){
           type = StringType.INSTANCE;
       }
       return type;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy