java 通过数据库映射生成thrift实体类

最近由于公司使用了thrift框架去做rpc,在生成thrift的实体类的时候,发现一个字段一个字段的去写非常麻烦和繁琐,在研究了thrift的代码生成方式之后打算通过数据库映射.thrift文件再通过执行thrift命令的方式来生成thrift实体类。

下面是详细代码:

ThriftGenerate.java

package generate;

import oracle.jdbc.OracleConnection;

import java.io.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ThriftGenerate {
    private Connection connection= null;
    private ResultSet resultSet = null;
    private FileWriter fw = null;
    private BufferedWriter bw = null;
    private static Properties properties = new Properties();
    private static String JDBC_DRIVER = "";
    private static String JDBC_URL = "";
    private static String JDBC_USER_NAME = "";
    private static String JDBC_PASSWORD = "";
    private static Pattern linePattern = Pattern.compile("_(\\w)");
    static{
       try {
            properties.load(ThriftGenerate.class.getClassLoader().getResourceAsStream("thrift.properties"));
            JDBC_DRIVER = properties.getProperty("jdbc.driver");
            JDBC_URL = properties.getProperty("jdbc.url");
            JDBC_USER_NAME = properties.getProperty("jdbc.userName");
            JDBC_PASSWORD = properties.getProperty("jdbc.password");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取数据库连接
     * @return
     */
    public Connection getConnection(){
        try {
            Class.forName(JDBC_DRIVER);
            this.connection = DriverManager.getConnection(JDBC_URL,JDBC_USER_NAME,JDBC_PASSWORD);
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return connection;
    };

    /**
     * 获取表信息
     * @param tableName
     */
    public String getTableName(String tableName){
        String name = "";
        try {
            DatabaseMetaData metaData = connection.getMetaData();
            /**
             * getTables方法参数解释
             * getTables(String catalog, String schemaPattern, String tableNamePattern, String types[])
             * catalog: 表所在类别名称,""表示获取没有类别的列,null表示获取所有类别的列 ORACLE不支持
             * schema: 表所在模式名称(oracle中对应于Tablespace);
             * ""表示获取没有模式的列,null标识获取所有模式的列;
             * 可包含单字符通配符("_"),或多字符通配符("%");
             * tableNamePattern: 表名称;可包含单字符通配符("_"),或多字符通配符("%");
             * types: 表类型数组; "TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS" 和 "SYNONYM";
             * null表示包含所有的表类型;可包含单字符通配符("_"),或多字符通配符("%");
             *
             */
            resultSet = metaData.getTables(null,"HLUP",tableName,Database.TABLE_TYPES);
            while (resultSet.next()){
                name= resultSet.getString(Database.TABLE_NAME);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        /**
         * 将表名转驼峰
         */
        if(name!=null && name.length()>0){
            name = name.toLowerCase();
            Matcher matcher = linePattern.matcher(name);
            StringBuffer sb = new StringBuffer();
            while(matcher.find()){
                matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
            }
            matcher.appendTail(sb);
            sb.setCharAt(0,Character.toUpperCase(sb.charAt(0)));
            return sb.toString();
        }
        return name;
    }

    /**
     * 获取字段信息
     * @param tableName
     */
    public List<String> getFieldInfos(String tableName){
        List<String> fieldInfos = new ArrayList<String>();
        try {
            DatabaseMetaData metaData = connection.getMetaData();

            resultSet = metaData.getColumns(null,"HLUP",tableName,null);
            int i=1;
            while (resultSet.next()){
                StringBuilder sb = new StringBuilder();
                sb.append("\t"+i+": ");
                //thrift 支持 boolean,byte,short,int,long,double,String,ByteBuffer,list,set,map 数据类型
                //在对ORACLE数据库的数据类型进行转换时,不能对应的一律转换为String类型(如DATE,TIMESTAMP,...),如存在小数位,则转换为double类型,如果是整数类型(如INTEGER)
                //且长度大于9的转换为long否则转换为int
                String columnName = humpColumnName(resultSet.getString(Database.COLUMN_NAME));
                String typeName = resultSet.getString(Database.TYPE_NAME);
                int columnSize = resultSet.getInt(Database.COLUMN_SIZE);
                int decimalDigits = resultSet.getInt(Database.DECIMAL_DIGITS);
                String remarks = resultSet.getString(Database.REMARKS);
                switch (typeName){
                    case Database.DataType.CHAR:
                        sb.append("string "+columnName);
                        break;
                    case Database.DataType.VARCHAR2:
                        sb.append("string "+columnName);
                        break;
                    case Database.DataType.LONG:
                        sb.append("string "+columnName);
                        break;
                    case Database.DataType.TIMESTAMP:
                        sb.append("string "+columnName);
                        break;
                    case Database.DataType.DATE:
                        sb.append("string "+columnName);
                        break;
                    case Database.DataType.INTEGER:
                        sb.append("i64 "+columnName);
                    case Database.DataType.NUMBER:
                        if (columnSize>9){
                            if (decimalDigits==0){
                                sb.append("i64 "+columnName);
                            }else {
                                sb.append("double "+columnName);
                            }
                        }else if (decimalDigits>0){
                            sb.append("double "+columnName);
                        }
                        break;
                    default:
                        sb.setLength(0);
                }
                sb.append(";//"+remarks+"\n");
                fieldInfos.add(sb.toString());
                i++;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return fieldInfos;
    }

    /**
     * 关闭连接
     */
    public void  close(){
        try {
            if(this.connection!=null){
                this.connection.close();
            }
            if(this.resultSet!=null){
                this.resultSet.close();
            }
            if(this.fw!=null){
                fw.close();
            }
            if(this.bw!=null){
                bw.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 将字段名转驼峰
     * @param columnName
     * @return
     */
    public String humpColumnName(String columnName){
        columnName = columnName.toLowerCase();
        Matcher matcher = linePattern.matcher(columnName);
        StringBuffer sb = new StringBuffer();
        while(matcher.find()){
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        sb.setCharAt(0,Character.toLowerCase(sb.charAt(0)));
        return sb.toString();

    }

    /**
     * 生成thrift文件
     */
    public File createFile(){
        String namespace = properties.getProperty("thrift.namespace");
        String dir = properties.getProperty("generate.dir");
        File file = new File(dir+"/generate.thrift");
        if (!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        if(file.exists()){
            file.delete();
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            fw = new FileWriter(file,false);
            bw = new BufferedWriter(fw);
            bw.write(namespace);
            bw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }

    /**
     * 内容写入文件
     * @param file
     * @param tableName
     * @param fieldInfos
     */
    private void addContentToFile(File file, String tableName, List<String> fieldInfos) {
        try {
            fw = new FileWriter(file,true);
            bw = new BufferedWriter(fw);
            bw.write("\nstruct "+tableName+" {\n");
            for (String fieldInfo : fieldInfos) {
                bw.write(fieldInfo);
            }
            bw.write("\n}");
            bw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 执行CMD命令
     */
    private static String excuteThriftCommand() {
        String dir = properties.getProperty("generate.dir");
        String command ="thrift -gen java generate.thrift";
        StringBuilder sb = new StringBuilder();
        Runtime run = Runtime.getRuntime();
        try {
            /**
             * 在指定目录下执行命令
             */
            Process process = run.exec(command,null,new File(dir));
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line = null;
            while ((line = bufferedReader.readLine()) != null) {
                sb.append(line + "\n");
            }
        }catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }
    public static void main(String[] args) {
        ThriftGenerate thriftGenerate = new ThriftGenerate();
        /**
         * 获取连接并打开获取备注
         */
        ((OracleConnection) thriftGenerate.getConnection()).setRemarksReporting(true);
        String[] tables = properties.getProperty("jdbc.tables").split(",");
        File file = thriftGenerate.createFile();
        for (String table : tables) {
            String tableName =  thriftGenerate.getTableName(table);
            List<String> fieldInfos = thriftGenerate.getFieldInfos(table);
            thriftGenerate.addContentToFile(file,tableName,fieldInfos);
        }
        thriftGenerate.close();
       String result =  excuteThriftCommand();
        System.out.println(result);
    }
}

Database.java

package generate;

public interface Database {
    /**
     * 表类别
     */
    public static final String TABLE_CAT = "TABLE_CAT";
    /**
     * 表模式
     */
    public static final String TABLE_SCHEM = "TABLE_SCHEM";
    /**
     * 表类型
     */
    public static final String TABLE_TYPE = "TABLE_TYPE";
    /**
     * 表名
     */
    public static final String TABLE_NAME = "TABLE_NAME";
    /**
     * 表备注
     */
    public static final String REMARKS = "REMARKS";
    /**
     * 表类型组
     */
    public static final String[] TABLE_TYPES = {"TABLE","VIEW"};
    /**
     * 列名
     */
    public static final String COLUMN_NAME = "COLUMN_NAME";
    /**
     * 对应的java.sql.Types的SQL类型(列类型ID)
     */
    public static final String DATA_TYPE = "DATA_TYPE";
    /**
     * java.sql.Types类型名称(列类型名称)
     */
    public static final String TYPE_NAME = "TYPE_NAME";
    /**
     * 列大小
     */
    public static final String COLUMN_SIZE = "COLUMN_SIZE";
    /**
     * 小数位数
     */
    public static final String DECIMAL_DIGITS = "DECIMAL_DIGITS";

    class DataType{
        public static final String CHAR = "CHAR";
        public static final String VARCHAR2 = "VARCHAR2";
        public static final String LONG = "LONG";
        public static final String NUMBER = "NUMBER";
        public static final String DATE = "DATE";
        public static final String TIMESTAMP = "TIMESTAMP(6)";
        public static final String INTEGER = "INTEGER";
    }

}

thrift.properties

#数据库连接信息
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:ORCL
jdbc.userName=***
jdbc.password=******
#要生成thrift实体类的表信息
jdbc.tables=TABLE1,TABLE2,TABLE3,TABLE4,TABLE5
#namespace
thrift.namespace=namespace java com.thrift.entity
generate.dir=F:/thrift

生成service的方式与生成实体类的方式类似

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值