根据Ibatis的SqlMap配置文件生成表结构


       有一份应用完整的源码,不过就是缺少了表结构,如果让我根据DO对象一个个去慢慢创建,也是个让人头痛的问题,一是因为有几十个表,二是这个东西拷贝粘贴一点技术含量都没有,这真不是我愿意干的活。本来是想在网上搜索一份这样的工具,关键字到是用了一大堆,中文英文都试过了,如“如何根据SqlMap创建表结构”、"How to generate table from sqlmap"等,还是木有找到,毕竟有几个是像我这样有对象源码却木有表结构的,于是就打算自己搞定了。
       幸好我对这份应用本身还是比较熟悉,知道用的是什么样的数据库,文件的命名风格是怎么样的等,想来根据对象生成表结构应该不是什么验事。刚开始想的方式是根据DO对象来生成,后来根据找到的MYSQL字段类型与JAVA对象的映射一看,发现一对多的情况有不少,觉得这种不靠谱,于是就放弃这种方案;后面发现SQLMPA配置文件中有对象与字段的映射,这个倒是省事了,直接分析这个文件就OK了,于是乎就有了下面这些代码:
[java] view plain copy
import java.io.BufferedReader;  
import java.io.File;  
import java.io.FileReader;  
import java.io.IOException;  
import java.io.StringReader;  
import java.util.List;  
  
import org.jdom.Document;  
import org.jdom.Element;  
import org.jdom.JDOMException;  
import org.jdom.input.SAXBuilder;  
import org.jdom.xpath.XPath;  
  
/** 
 * 根据Ibatis的SqlMap配置文件,重新生成表结构。<br> 
 * 要求所有的sqlmap中对应的字段都有jdbcType这个属性。 
 *  
 * @author Administrator 2012-7-2 下午09:33:07 
 */  
public class Sqlmap2Table {  
  
    // 默认所有的varchar都是512,可以保证满足绝大多数的字段  
    private static final String DEFAULT_VARCHAR_LENGTH = "VARCHAR(256)";  
  
    public static void main(String[] args) throws JDOMException, IOException {  
        String sqlMapPath = "I:/Site/proc/xxx_trunk/dal/src/conf";//这里指定你的sqlmap配置文件所在路径  
        analysis(sqlMapPath);  
    }  
  
    /** 
     * 根据指定的目录进行遍历分析 
     *  
     * @param path 
     * @throws IOException 
     * @throws JDOMException 
     */  
    private static void analysis(String path) 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());  
                } else {  
                    analysisSqlMap(file.getAbsolutePath());  
                }  
            }  
        }  
    }  
  
    /** 
     * 分析单个的sqlmap配置文件 
     *  
     * @param sqlMapFile 
     * @throws IOException 
     * @throws JDOMException 
     */  
    private static void analysisSqlMap(String sqlMapFile) throws IOException, JDOMException {  
        // System.out.println(sqlMapFile);  
        /** 
         * 这里要把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);  
        List<Element> resultMap = (List<Element>) XPath.selectNodes(doc, "//resultMap");  
        for (Element e : resultMap) {  
            String alias = e.getAttributeValue("class");  
            String tableName = getTableName(doc, alias);  
            List<Element> children = e.getChildren();  
            StringBuilder createTableString = new StringBuilder("create table " + tableName + "(\n\t");  
            int size = 0;  
            for (Element child : children) {  
                String jdbcType = child.getAttributeValue("jdbcType");  
                if (jdbcType.toUpperCase().equals("VARCHAR")) {  
                    jdbcType = DEFAULT_VARCHAR_LENGTH;  
                }  
                createTableString.append(child.getAttributeValue("column")).append(" ").append(jdbcType);  
                if (size < children.size() - 1) {  
                    createTableString.append(",\n\t");  
  
                } else {  
                    createTableString.append("\n");  
                }  
                size++;  
            }  
            createTableString.append(")");  
            System.out.println(createTableString.toString().toUpperCase());  
        }  
    }  
  
    private static String getTableName(Document doc, String alias) throws JDOMException {  
        String tableName = "";  
        String classPath = null;  
        // 这里的alias可能是一个别名,也可能是一个java类路径,这里我通过该alias是否有点"."这个符号来区别  
        if (alias.indexOf(".") > 0) {// 是JAVA类  
            classPath = alias;  
        } else {// 是别名,就到配置的别名中去找  
            Element aliasElement = (Element) XPath.selectSingleNode(doc, "//typeAlias[@alias=\"" + alias + "\"]");  
            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 static 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 static Document getDocument(String xmlString) throws JDOMException, IOException {  
  
        SAXBuilder builder = new SAXBuilder();  
        Document anotherDocument = builder.build(new StringReader(xmlString));  
        return anotherDocument;  
  
    }  
}  
    这里需要JDOM的依赖。
    不过需要注意几点:
    1、这里体现不出主键、外键关系,没办法,这里只有手工补充了;
    2、每个sqlmap的文件中,每个resultMap中的result字段,都必须有jdbcType这一行,否则会报找不到属性的空指针异常,当然这里可以搞一个javaType与jdbcType的映射关系,根据javaType去找jdbcType,我这里用不着,就没有弄了;
    3、sqlmap的DOCTYPE在读出来的时候要去掉,否则生成对象的时候会报错。
    差不多了,我是跑成功了。
 

猜你喜欢

转载自blog.csdn.net/z453588/article/details/84185736
今日推荐