需求
最近在做一个中间库的映射表(加载两个表信息的字段映射匹配),需要加载数据库表字段的详细信息,即列的信息,比如:字段名,字段类型,字段长度,描述…等。其中的踩坑点在此记录一下。
核心方法
ResultSet columnSet = dbmd.getColumns(null, "%", clz, "%");
原型:ResultSet DatabaseMetaData getColumns(String catalog,String schema,String tableName,String columnName);
参数说明:
参数catalog : 类别名称
参数schema : 用户方案名称
参数tableName : 数据库表名称
参数columnName : 列名称
思路分析
- jdbc获取链接;
- 获取表中所有字段信息;
- 处理空值以及根据实际业务变化;
代码
其中,有两种实现方法:
- 使用ResultSetMetaData获取数据库表信息(即执行sql语句返回的resultSet)
- 使用DatabaseMetaData获取数据库表信息(效率更高点)
//使用DatabaseMetaData获取数据库表信息
public static List<String> getMetaDataDbmd(String clz,String url,String user,String password) throws SQLException {
Connection conn = getConnection(url,user,password);
List<String> list = new ArrayList<String>();
try {
DatabaseMetaData dbmd = conn.getMetaData();
ResultSet columnSet = dbmd.getColumns(null, "%", clz, "%");
while (columnSet.next()) {
StringBuffer sb = new StringBuffer();
String decimalDigits = columnSet.getString("DECIMAL_DIGITS");
String typeName = columnSet.getString("TYPE_NAME");
sb.append(columnSet.getString("COLUMN_NAME") + ",");//字段名
if("NUMBER".equals(typeName)){
typeName = Optional.ofNullable(decimalDigits).map(a -> a = "NUMBER_DIGITS").orElse("NUMBER");
}
sb.append(typeName + ",");//字段类型
sb.append(columnSet.getString("COLUMN_SIZE") + ",");//字段长度
sb.append(columnSet.getString("NULLABLE") + ",");//是否为空 0为非空,1为空
sb.append(columnSet.getString("DECIMAL_DIGITS") + ",");//小数部分的位数
sb.append(columnSet.getString("REMARKS")==null?" ":URLEncoder.encode(columnSet.getString("REMARKS"), "UTF-8"));
list.add(sb.toString());
}
} catch (SQLException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}finally {
closeConnection(conn);
}
return list;
}
//使用ResultSetMetaData获取数据库表信息
public static List<String> getMetaDataRsmd(String clz) {
Connection conn = getConnection();
List<String> list = new ArrayList<String>();
try {
Statement stmt = conn.createStatement();
String sql = "select * from " + clz;
ResultSet rs = stmt.executeQuery(sql);
ResultSetMetaData rsmd = rs.getMetaData();
int count = rsmd.getColumnCount();
for (int i = 1; i <= count; i++) {
StringBuffer sb = new StringBuffer();
sb.append(rsmd.getColumnName(i) + ",");
sb.append(rsmd.getColumnTypeName(i) + ",");
sb.append(rsmd.getPrecision(i));
list.add(sb.toString());
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
期间遇到的问题
在处理过程中,可能会发现使用getTables获取表的信息时 无法获取remarks信息,试试按照下面方法重新配置一下驱动:
//oracle版本
public Connection getConnection(String username,String password,String host,String port,String database) {
Connection con = null;
Properties props =new Properties();
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@"+host+":"+port+":"+database;
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("remarks", "true");//设置可以获取remarks信息
con = DriverManager.getConnection(url, props);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return con;
}
//mysql版本
public Connection getConnection(String username,String password,String host,String port,String database) {
Connection con = null;
Properties props =new Properties();
try {
//Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://"+host+":"+port+"/"+database+"?useUnicode=true&characterEncoding=UTF8";
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("remarks", "true"); //设置可以获取remarks信息
props.setProperty("useInformationSchema", "true");//设置可以获取tables remarks信息
con = DriverManager.getConnection(url, props);
} catch (SQLException e) {
e.printStackTrace();
}
return con;
}