最近由于公司使用了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的方式与生成实体类的方式类似