java根据xml中插入语句生成创建表字段

该文章主要内容

1.目前从工程的xml中生成sql是从sqlmapper的resultMap生成创建表语句

该方案有明显的局限性质,
1.查询语句不是标准的带有resultMap的语句,会忽略该表生成
2.同一样一个表查询有多种变种形式,那对应就会有多种resultMap,处理只相差几个字段的resultMap其实生成的字段可能还不一样
3.resultMap多层嵌套,导致表创建语句的复杂性

2.该方案的实现方式

1.根据插入语句生成创建表语句,因为一个工程中插入数据的地方基本在一个文件,而且插入基本就是一条语句就解决,没有复杂的嵌套循环插入
2.能准确区别该模块生产数据表和依赖基础数据表
有插入语句代表这个表是这个模块生产的数据,那这个表就一定需要创建,在一个模块中肯定存在没有插入语句但是又存在查询表语句的表,那这一类表就统一归为该模块依赖的基础数据表,
为什么需要这么明确的区分,因为依赖的基础数据表是需要我们在运行之前导入基础数据的,而造基础数据是涉及到该模块是否能运行起来的关键

3.该方案的实现模块细节方法解释

1.main方法
指定生成创建sql的文件夹位置以及文件名
指定sqlMapper在代码工程中的位置
2.buildInsertSql2Table
生成建表sql文件方法,打印出现超过>=2的表的表名字以及汇总等analysis执行完成之后再生成创建表sql
3.analysis
根据指定的目录进行遍历分析,直到是xml文件才执行analysisSql方法
4.analysisSql
获取xml中的sql文件,有写自增索引的特殊处理, 获取命名空间(nameSpace)
分析单个的sqlmap配置文件
只处理insert方法
根据mapper的命名空间和调用方法获取插入sql的入参class  getMethodParamClass
生成插入sql语句 createTable创建表中包括
	替换dateformat日期类型为默认字段createTime
	数据库表字段需要将\n,(,)替换为逗号
	vo字段列需要将空格,#{,}都替换为空,使用,分割
	没有id主键的自动补齐主键
	统计对同一表有重复创建表的sql,需要用户手动合并两个表
	创建表头语句,包括drop语句,create语句,以及表尾部括号
	创建表列语句 createCloumns
		根据表字段和vo映射字段生成表列字段
		根据vo字段动态构建jdbcType
		如果为id主键,增加自增定义
		有重复的插入语句使用map去重
		返回特定占位符,方便替换
	有重复出现的表,则需要在map中做列字段汇总
	将生成的sql写入文件 writeSql2File

4.文件执行调用方式

1.先指定main方法中的sql生成位置,以及sqlMapper的位置
2.先执行一次方法,会在控制台打印出有哪些表重复[出现两条创建表语句的表名为],把这些表复制放入
String[] tableAppearFrequency中
3.再次执行main方法,因为tableAppearFrequency有重复的插入表明,所以会对重复的插入语句有不同的;列进行自动汇总
4.执行完成之后打开sql目录即可查看创建的创建表语句了
5.除了这些之外的查询表怎么获取??? 使用EmEditor直接搜索from和join关键字,然后进行各种变化操作获取到所有的查询的表明,之后用for循环进行去重即可获得基础表数据是哪些表

package com.sqlmap2Table;
import com.alibaba.fastjson.JSON;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.jdom.*;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;
/**
 * @description 根据xml的insert语句生成表创建语句
 * @author pengXiong
 * @date 2020/8/5 19:19
 */
public class Sqlmap2Table {

    public static Sqlmap2Table instance = new Sqlmap2Table();
    // 默认所有的varchar都是512,可以保证满足绝大多数的字段
    private final String DEFAULT_VARCHAR_LENGTH = "varchar(256)";

    // 有多条插入语句生成的create表做占位使用,方便替换
    private final String COLUMN_PLACEHOLDER = "%Cloumns%";

    private final String SELF_INCRECE_PRIMARY_KEY = "id";
    private final String SELF_INCRECE_PRIMARY_VALUE = " primary key auto_increment";


    // 统计对同一表有重复创建表的sql,需要用户手动合并两个表
    private Map<String, Integer> tableAppearFrequency = new HashMap<>();

    private Map<String, Map<String, String>> combinaTableAppearFrequency = new HashMap<>() ;

    private Sqlmap2Table() {
        // 放置重复出现的需要组合的表和表字段,最后完成后统一写文件, 该重复表key值运行一次后请从打印日志[出现两条创建表语句的表名为 : ]中取到
        String[] tableAppearFrequency = new String[]{
        // 出现两条创建表语句的表名 放入这里
                ""
        };
        for (String str : tableAppearFrequency) {
            combinaTableAppearFrequency.put(str, new HashMap<>());
        }
    }



    public static void main(String[] args) throws JDOMException, IOException {

        
        String sqlFile = "I:/IT/创建表/create_table.sql";
        String sqlMapPath = "I:/IT/server/src/main/resources/mybatis/mapper";//这里指定你的sqlmap配置文件所在路径
        // 统计对同一表有重复创建表的sql,需要用户手动合并两个表
        Sqlmap2Table.instance.buildInsertSql2Table(sqlMapPath, sqlFile);

    }

    /**
     * 打印出现超过>=2的表的表名字以及汇总等analysis执行完成之后再生成创建表sql
     * @param sqlMapPath 
     * @param sqlFilePath
     * @throws IOException
     * @throws JDOMException
     */
    public void buildInsertSql2Table(String sqlMapPath, String sqlFilePath) throws IOException, JDOMException {
        // 先将文件删除
        File sqlFile = new File(sqlFilePath);
        sqlFile.delete();
        // 生成建表sql文件方法
        analysis(sqlMapPath,sqlFilePath);
        // 打印出现超过>=2的表的表名字
        List<Map.Entry> result = tableAppearFrequency.entrySet().stream().filter(table -> table.getValue()>=2).collect(Collectors.toList());
        System.out.println("出现两条创建表语句的表名和出现数量为 : "+ JSON.toJSONString(result));
        System.out.println("出现两条创建表语句的表名为 : "+ JSON.toJSONString(result.stream().map(tabl -> tabl.getKey()).toArray()));
        // 对重复出现表的表字段在map中汇总等analysis执行完成之后再生成创建表sql
        if (MapUtils.isNotEmpty(combinaTableAppearFrequency)) {
            for (Map.Entry<String, Map<String, String>> entry : combinaTableAppearFrequency.entrySet()) {
                Map<String, String> colunmMap = entry.getValue();
                String sql = colunmMap.get(COLUMN_PLACEHOLDER);
                StringBuffer sbCloumns = new StringBuffer();
                for (Map.Entry<String, String> coluns : colunmMap.entrySet()) {
                    String key = coluns.getKey();
                    String value = coluns.getValue();
                    if (Objects.equals(key, COLUMN_PLACEHOLDER)) {
                        continue;
                    }
                    // 构建表列参数
                    sbCloumns = buildCloumns(sbCloumns, key, value);
                }
                sql = sql.replace(COLUMN_PLACEHOLDER, sbCloumns.toString());
                // 将生成的sql写入文件
                writeSql2File(sql, sqlFilePath);
            }
        }
    }

    /**
     * 根据指定的目录进行遍历分析
     *
     * @param path
     * @throws IOException
     * @throws JDOMException
     */
    private void analysis(String path, String sqlFile) throws IOException, JDOMException {
        File filePath = new File(path);
        if (filePath.isDirectory() && !filePath.getName().equals(".svn")) {
            File[] fileList = filePath.listFiles();
            for (File file : fileList) {
                if (file.isDirectory()) {
                    analysis(file.getAbsolutePath(),sqlFile);
                } else {
                    analysisSql(file.getAbsolutePath(),sqlFile);
                }
            }
        }
    }


    /**
     * 分析单个的sqlmap配置文件
     *
     * @param sqlMapFile
     * @throws IOException
     * @throws JDOMException
     */
    private void analysisSql(String sqlMapFile, String sqlFilePath) throws IOException, JDOMException {
        // System.out.println("************"+sqlMapFile);
        boolean isNull=false;
        /**
         * 这里要把sqlmap文件中的这一行去掉:<br>
         * <!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd"><br>
         * 否则JDom根据文件创建Document对象时,会报找不到www.ibatis.com这个异常,导致渲染不成功。
         */
        String xmlString = filterRead(sqlMapFile, "<!DOCTYPE");
        Document doc = getDocument(xmlString);
        Element foo = doc.getRootElement();
        // sql统一转换为小写,并且替换sql中的关键字字符
        String sqlStr = generateKeyWords(foo);
        // 获取拆分出的sql
        List<String> sqls = Arrays.asList(sqlStr.split(";")).parallelStream().filter( sql -> {
            return // sql不为空
                    StringUtils.isNotBlank(sql)
                            // 不包含last_insert_id,last_insert_id会被拆成两个放入list中
                            && !sql.contains("last_insert_id()");
            //&& !sql.contains("LAST_INSERT_ID()");
        }).collect(Collectors.toList());
        // 获取命名空间
        String mapper = ((Attribute)foo.getAttributes().get(0)).getValue();

        // 获取sql中Element的具体信息
        List<Element> allChildren = foo.getChildren();
        for(int i=0; i<allChildren.size(); i++) {
            Element element = allChildren.get(i);
            // 获取当中的某一条sql
            String operatorType = element.getName();
            if (!"insert".equals(operatorType)) {
                // 只按照insert方法处理
                continue;
            }
            // 获取执行的sql
            String sql = sqls.get(i);
            if(!sql.contains("insert") || sql.contains("@")) {
                // 特殊场景处理,
                // 1.有的sql包含查询语句,将该数据剔除
                // 2.存储过程暂时先不生成sql
                System.out.println("这是一条存储过程sql : "+sql);
                continue;
            }
            // 根据mapper和调用方法获取插入sql的入参class
            Class[] paramClass = getMethodParamClass(mapper, element);
            System.out.println("contentSql : "+sql);
            // 生成插入sql语句
            String createTableSql = createTable(sql, paramClass);
            System.out.println("createTableSql : "+createTableSql);
            // 将生成的sql写入文件
            writeSql2File(createTableSql, sqlFilePath);
        }
    }


    /**
     * sql统一转换为小写,并且替换sql中的关键字字符
     * @param foo 单个sql元素
     * @return 替换后的sql
     */
    private String generateKeyWords(Element foo) {
        String sqlStr = foo.getValue().toLowerCase();
        sqlStr = sqlStr
                .replace("\n", "")
                .replace("insert ", ";insert ")
                .replace("update ", ";update ")
                .replace("delete ", ";delete ")
                .replace("select ", ";select ");
        return sqlStr;
    }


     /**
     * 根据mapper和调用方法获取插入sql的入参class
     * @param mapper dao层映射
     * @param element 单个插入sql元素
     * @return
     */
    private Class[] getMethodParamClass(String mapper, Element element){
        List<Attribute> elementAttrs = element.getAttributes();
        // 获取sql配置方法的名称,可以字段为id
        String methodName = null;
        for (Attribute att : elementAttrs) {
            if ("id".equals(att.getName())) {
                methodName = att.getValue();
                break;
            }
        }
        Class<?> mapperClass  = null;
        try {
            mapperClass = Class.forName(mapper);
        } catch (ClassNotFoundException e) {
            System.out.println("ClassNotFoundException Message : "+e.getMessage()+"mapperClass :"+JSON.toJSONString(mapperClass));
            e.printStackTrace();
        }
        Method[] methods = mapperClass.getMethods();
        for(Method method : methods) {
            if(methodName.equals(method.getName())) {
                // 判定是不是有泛型参数
                boolean havaGenericparam =
                        Arrays.asList(method.getGenericParameterTypes()).stream().allMatch( param -> param.getTypeName().contains("<"));
                if (!havaGenericparam) {
                    // 不是泛型直接返回参数类型
                    return method.getParameterTypes();
                } else {
                    // 泛型参数需要获取泛型类型<>尖括号中的真正数据类型
                    Type[] types = method.getGenericParameterTypes();
                    Class[] clazz = new Class[types.length];
                    for (int i=0; i<types.length; i++ ) {
                        String paramClazz = types[i].getTypeName();
                        if (paramClazz.contains("Map")) {
                            // Map<String, String>泛型截取最后一个String
                            paramClazz = (paramClazz = types[i].getTypeName()).substring(paramClazz.lastIndexOf(", ")+1, paramClazz.indexOf(">"));
                        } else if (paramClazz.contains("<")) {
                            // List<String>泛型截取最后一个String
                            paramClazz = (paramClazz = types[i].getTypeName()).substring(paramClazz.lastIndexOf("<")+1, paramClazz.indexOf(">"));
                        }
                        try {
                            // 获取到泛型中真正的参数后实例化为class
                            clazz[i] = Class.forName(paramClazz.trim());
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        }
                    }
                    return clazz;
                }
            }
        }
        throw new IllegalArgumentException("class : "+ mapper+" 不存在这种类型的数据");
    }


    /**
     * 根据插入sql语句和对应入参生成sql语句方法
     * @param sql 插入sql语句
     * @param paramClass 插入sql语句对应的入参
     * @return
     */
    private String createTable(String sql, Class[] paramClass) {
        StringBuffer sb = new StringBuffer();
        // 替换dateformat日期类型为默认字段createTime
        sql = replaceDateFormatSql(sql);
        String reg = "[ ,\n,\t,#{,}(,)]";
        // 数据库表字段需要将\n,(,)替换为逗号
        String[] cloumns = sql.substring(indexOfInto(sql),indexOfCloumn(sql, false))
                .replaceAll(reg, ",")
                .split(",");
        // vo字段列需要将空格,#{,}都替换为空,使用,分割
        String[] voCloumns = sql.substring(indexOfCloumn(sql, true),sql.lastIndexOf("}"))
                .replaceAll(reg, ",")
                .split(",");
        List<String> cloumnLists = Arrays.asList(cloumns).parallelStream().distinct().filter(cloum -> StringUtils.isNotBlank(cloum)).collect(Collectors.toList());
        List<String> voCloumnLists = Arrays.asList(voCloumns).parallelStream().distinct().filter(cloum -> StringUtils.isNotBlank(cloum) && !cloum.contains("jdbcType")).collect(Collectors.toList());
        System.out.println("cloumnLists : "+JSON.toJSONString(cloumnLists) + " voCloumnLists : "+ JSON.toJSONString(voCloumnLists));
        if (cloumnLists.size()-1 !=  voCloumnLists.size()) {
            // 特殊场景处理, 当没有括号中间有values值时,会将values也归入表列数组中,当两个数量不相等时强制剔除一个
            cloumnLists.remove(cloumnLists.size()-1);
        }
        // 没有id主键的自动补齐主键
        if (!cloumnLists.contains(SELF_INCRECE_PRIMARY_KEY)) {
            cloumnLists.add(SELF_INCRECE_PRIMARY_KEY);
            voCloumnLists.add(SELF_INCRECE_PRIMARY_KEY);
        }

        String table = cloumnLists.get(0);
        // 统计对同一表有重复创建表的sql,需要用户手动合并两个表
        if (tableAppearFrequency.containsKey(table)) {
            tableAppearFrequency.put(table, tableAppearFrequency.get(table)+1);
        } else {
            tableAppearFrequency.put(table, 1);
        }
        // 表存在则删除表
        sb.append("\n").append("/**************************[ "+ table+" ]***************************/\n");
        sb.append("DROP TABLE IF EXISTS ").append(table).append(";\n");
        // 创建表头语句
        sb.append("CREATE TABLE ").append(table).append("(");
        // 移除第一个表明位置
        cloumnLists.remove(0);

        try {
            String cloumn = createCloumns(cloumnLists, voCloumnLists, paramClass, table);
            sb.append(cloumn);
        } catch (Exception e) {
            System.out.println("createCloumns Exception , Message : "+e.getMessage());
            System.out.println("cloumnLists : "+cloumnLists + " voCloumnLists : "+voCloumnLists + " paramClass : "+paramClass.toString());
        }
        // 创建表尾部
        sb.append(");");
        boolean haveAppearFrequencyInsert = combinaTableAppearFrequency.containsKey(table);
        if (haveAppearFrequencyInsert) {
            Map<String, String> tableInfo = combinaTableAppearFrequency.get(table);
            tableInfo.put(COLUMN_PLACEHOLDER, sb.toString());
            combinaTableAppearFrequency.put(table, tableInfo);
            return "";
        } else {
            return sb.toString();
        }
    }

    /**
     * 根据表字段和vo映射字段生成表列字段
     * @param cloumnLists 表字段
     * @param voCloumnLists vo映射字段
     * @param paramClass vo映射入参对象
     * @return
     */
    private String createCloumns(List<String> cloumnLists, List<String> voCloumnLists, Class[] paramClass, String table) {
        // 出现多条插入语句使用map对列名去重
        boolean haveAppearFrequencyInsert = combinaTableAppearFrequency.containsKey(table);
        Map<String, String> frequencyInsertcolumn = combinaTableAppearFrequency.get(table);
        // 创建sql列名部分
        StringBuffer sbCloumns = new StringBuffer();
        for (int i = 0; i < cloumnLists.size(); i++ ) {
            String cloumn = cloumnLists.get(i);
            String voCloumn = voCloumnLists.get(i);
            String jdbcType=null;
            for (Class clazz : paramClass) {
                // 根据vo字段动态构建jdbcType
                try {
                    jdbcType = getJdbcType(clazz, voCloumn);
                    if (null != jdbcType) {
                        break;
                    }
                } catch (NoSuchFieldException e) {
                    System.out.println("clazz : "+clazz.getName() + " voCloumn : "+voCloumn);
                    e.printStackTrace();
                }
            }
            boolean isSelfIncreceKey = Objects.equals(cloumn, SELF_INCRECE_PRIMARY_KEY);
            // 如果为id主键,增加自增定义
            jdbcType = isSelfIncreceKey ? jdbcType + SELF_INCRECE_PRIMARY_VALUE : jdbcType;
            if (haveAppearFrequencyInsert) {
                // 有重复的插入语句使用map去重
                frequencyInsertcolumn.put(cloumn, jdbcType);
            } else {
                sbCloumns = buildCloumns(sbCloumns, cloumn, jdbcType);
            }
         }
            if (haveAppearFrequencyInsert) {
                combinaTableAppearFrequency.put(table, frequencyInsertcolumn);
                // 返回特定占位符,方便替换
                return COLUMN_PLACEHOLDER;
            } else {
                return sbCloumns.toString();
            }
    }

    /**
     * 构建表列参数,可以将主键Id置为第一列
     * @param sbCloumns 已经组装的一部分列数据
     * @param cloumn mysql数据字段名
     * @param jdbcType mysql数据类型
     * @return
     */
    private StringBuffer buildCloumns(StringBuffer sbCloumns, String cloumn, String jdbcType) {
        // 是否为id主键
        boolean isSelfIncreceKey = Objects.equals(cloumn, SELF_INCRECE_PRIMARY_KEY);
        // 将主键放在第一列
        if (isSelfIncreceKey) {
            StringBuffer selfIncreceKeySb = new StringBuffer();
            selfIncreceKeySb.append("\n")
                    .append(cloumn)
                    .append(" ")
                    .append(jdbcType)
                    .append(",")
                    .append(sbCloumns);
            sbCloumns = selfIncreceKeySb;
        } else {
            if (!"".equals(sbCloumns.toString())) {
                sbCloumns.append(",");
            }
            sbCloumns.append("\n")
                    .append(cloumn)
                    .append(" ")
                    .append(jdbcType);
        }
        return sbCloumns;
    }

    /**
     * 将生成的sql写入文件
     * @param sql 生成的创建表sql语句
     * @param sqlFilePath 生成的文件位置
     */
    private void writeSql2File(String sql, String sqlFilePath) {
        File sqlFile = new File(sqlFilePath);
        FileOutputStream fos = null;
        OutputStreamWriter osw = null;
        try {
            if (!sqlFile.exists()) {
                boolean hasFile = sqlFile.createNewFile();
                if(hasFile){
                    System.out.println("file not exists, create new file");
                }
                fos = new FileOutputStream(sqlFile);
            } else {
//                System.out.println("file exists");
                fos = new FileOutputStream(sqlFile, true);
            }
            osw = new OutputStreamWriter(fos, "utf-8");
            osw.write(sql); //写入内容
            osw.write("\n");  //换行
        } catch (Exception e) {
            e.printStackTrace();
        }finally {   //关闭流
            try {
                if (osw != null) {
                    osw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 替换dateformat日期类型为默认字段createTime
     * @param sqlStr
     * @return
     */
    private String replaceDateFormatSql(String sqlStr) {
        StringBuffer stringBuffer = new StringBuffer();
        boolean sqlContainsDateFormat = sqlStr.contains("date_format");
        if (!sqlContainsDateFormat) {
            return sqlStr;
        }
        // 开始部分部分到date_format
        String startSql = sqlStr.substring(0, sqlStr.indexOf("date_format("));
        // 结束部分从第一个sysdate()开始 +9为减去长度, +1为减去括号的长度
        String endSql = sqlStr.substring(sqlStr.indexOf(")", sqlStr.indexOf("sysdate()")+9) +1);
        stringBuffer.append(startSql)
                .append("#{createTime}")
                .append( replaceDateFormatSql(endSql));
        return stringBuffer.toString();
    }

    /**
     * 获取插入语句into开始位置
     * @param sql
     * @return
     */
    private int indexOfInto(String sql){
        return sql.indexOf("into")+4;
    }

    /**
     * 获取vo映射字段 #{的开始位置
     * @param sql
     * @param isStart 获取开始位置还是结束位置
     * @return
     */
    private int indexOfCloumn(String sql, boolean isStart){

        if (isStart) {
            return sql.indexOf("#{");
        } else {
            if (sql.indexOf(")") != -1) {
                return sql.indexOf(")");
            } else {
                // 兼容没有括号的sql
                return sql.indexOf("#{")-1;
            }
        }
    }

    /**
     * 通过获取到的voCloumn字段映射到vo中获取对应类型
     * @param clazz 对应vo入参对象
     * @param voCloumn 列名映射字段名
     * @return
     */
    private String getDeclaredField (Class<?> clazz, String voCloumn) {
        Field[] fields = clazz.getDeclaredFields();
        String fieldType = null;
        for (Field field : fields) {
            if(voCloumn.equalsIgnoreCase(field.getName())) {
                fieldType =  field.getGenericType().getTypeName();
                break;
            }
        }
        if (StringUtils.isBlank(fieldType)) {
            System.out.println("clazz : "+ clazz.getName() +", voCloumn : "+voCloumn);
            // java.lang.Object往上没有父类了,再递归调用会有空指针,需要提前返回
            if ( null == clazz.getSuperclass() || "java.lang.Object".equals(clazz.getSuperclass().getName())) {
                return "java.lang.Object";
            }
            return getDeclaredField(clazz.getSuperclass(), voCloumn);
        }
        return fieldType;
    }

    /**
     * 根据映射vo的字段名和mySql中的类型一一对应转换
     * @param clazz 映射vo的对象
     * @param voCloumn 映射vo的字段名
     * @return
     * @throws NoSuchFieldException
     */
    private String getJdbcType(Class<?> clazz, String voCloumn) throws NoSuchFieldException {
        // 含有点的数据,从点取到最后
        voCloumn = voCloumn.contains(".") ? voCloumn.substring(voCloumn.indexOf(".")+1) : voCloumn;
        String fieldType = getDeclaredField(clazz, voCloumn);
        switch (fieldType){
            case "java.lang.String":
            case "java.lang.Object":
                return DEFAULT_VARCHAR_LENGTH;
            case  "java.lang.Character":
            case "char":
                return "CHAR";
            case "java.math.BigInteger":
                return "bigint(20)";
            case "java.lang.Integer":
            case "int":
                return "int(11)";
            case "java.lang.Long":
            case "long":
                return "int(20)";
            case "java.math.BigDecimal":
                return"decimal(10,2)";
            case "java.lang.Number":
                return "decimal(10,2)";
            case "java.lang.Double":
                return"double";
            case "java.lang.Boolean":
            case "boolean":
                return"tinyint(1)";
            case "java.lang.Float":
            case "float":
                return "float";
            case "java.util.Date":
                return "datetime";
            case "java.sql.Timestamp":
                return "timestamp";
            default:
                return null;
        }
    }

    /**
     * 该方法暂时无用
     * @param doc
     * @param alias
     * @return
     * @throws JDOMException
     */
    private String getTableName(Document doc, String alias) throws JDOMException {
        String startPath = "//typeAlias[@alias=\"";
        String endPath = "\"]";
        String tableName = "";
        String classPath = null;
        // 这里的alias可能是一个别名,也可能是一个java类路径,这里我通过该alias是否有点"."这个符号来区别
        if (alias.indexOf(".") > 0) {// 是JAVA类
            classPath = alias;
        } else {// 是别名,就到配置的别名中去找
            String path = startPath+alias+endPath;
            Element aliasElement = (Element) XPath.selectSingleNode(doc, path);
            classPath = aliasElement.getAttributeValue("type");
        }
        String[] classPathArray = classPath.split("\\.");
        // 取到DO的名称
        classPath = classPathArray[classPathArray.length - 1];
        int i = classPath.lastIndexOf("DO");
        // 取到根据表名生成的DO名称,无“DO”两个字符
        classPath = classPath.substring(0, i);
        char[] chars = classPath.toCharArray();
        boolean isFirst = Boolean.TRUE;
        // 生成真实的表名
        for (char c : chars) {
            if (!isFirst && c >= 65 && c <= 90) {
                tableName += "_";
            }
            if (isFirst) {
                isFirst = Boolean.FALSE;
            }
            tableName += c;
        }
        // 表名转换为大写返回
        return tableName.toUpperCase();
    }

    /**
     * 过滤性阅读
     *
     * @param filePath 文件路径
     * @param notIncludeLineStartWith 不包括的字符,即某行的开头是这样的字符串,则在读取的时候该行忽略
     * @return
     * @throws IOException
     */
    private String filterRead(String filePath, String notIncludeLineStartWith) throws IOException {
        String result = "";
        FileReader fr = new FileReader(filePath);
        BufferedReader br = new BufferedReader(fr);
        String line = br.readLine();
        while (line != null) {
            if (!line.startsWith(notIncludeLineStartWith)) {
                result += line;
            }
            line = br.readLine();
            if (line != null && !line.startsWith(notIncludeLineStartWith)) {
                result += "\n";
            }
        }
        br.close();
        fr.close();
        return result;
    }

    /**
     * 根据XML 字符串 建立JDom的Document对象
     *
     * @param xmlString XML格式的字符串
     * @return Document 返回建立的JDom的Document对象,建立不成功将抛出异常。
     * @throws IOException
     * @throws JDOMException
     */
    private Document getDocument(String xmlString) throws JDOMException, IOException {
        System.out.println("xmlString : "+xmlString);
        SAXBuilder builder = new SAXBuilder();
        Document anotherDocument = builder.build(new StringReader(xmlString));
        return anotherDocument;

    }

}

java读取xml文件的四种方法
根据mybatis/ibatis sqlmapper文件解析生成数据库表
根据mybatis-generator自动生成的mapper来逆向生成数据库sql文件
根据mybatis/ibatis sqlmapper文件解析生成数据库表

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值