修复Oracle下特殊表名导致meta信息获取不到问题

This commit is contained in:
Looly 2024-04-29 13:58:36 +08:00
parent 6d65106b80
commit 3c7377bf0c
3 changed files with 113 additions and 55 deletions

View File

@ -12,6 +12,8 @@
package org.dromara.hutool.db.meta; package org.dromara.hutool.db.meta;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.convert.Convert;
import org.dromara.hutool.core.lang.wrapper.SimpleWrapper; import org.dromara.hutool.core.lang.wrapper.SimpleWrapper;
import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil; import org.dromara.hutool.core.util.ObjUtil;
@ -21,10 +23,7 @@ import java.sql.Connection;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.LinkedHashMap; import java.util.*;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
/** /**
* 用于封装DatabaseMetaData对象并提供特定数据库的元数据访问 * 用于封装DatabaseMetaData对象并提供特定数据库的元数据访问
@ -111,6 +110,26 @@ public class DatabaseMetaDataWrapper extends SimpleWrapper<DatabaseMetaData> {
} }
} }
public List<String> getTableNames(final String tableNamePattern, final TableType... types){
List<String> result = null;
try (final ResultSet rs = this.raw.getTables(catalog, schema, tableNamePattern, Convert.toStrArray(types))) {
if (null != rs) {
result = new ArrayList<>(rs.getFetchSize());
String table;
while (rs.next()) {
table = rs.getString("TABLE_NAME");
if (StrUtil.isNotBlank(table)) {
result.add(table);
}
}
}
} catch (final SQLException e){
throw new DbException(e);
}
return CollUtil.emptyIfNull(result);
}
/** /**
* 获取指定表的备注信息 * 获取指定表的备注信息
* *
@ -205,6 +224,35 @@ public class DatabaseMetaDataWrapper extends SimpleWrapper<DatabaseMetaData> {
return indexInfoMap; return indexInfoMap;
} }
/**
* 获得表的所有列名
*
* @param tableName 表名
* @return 列数组
* @throws DbException SQL执行异常
*/
public String[] getColumnNames(String tableName) {
final String catalog = this.catalog;
final String schema = this.schema;
// issue#I9BANE Oracle中特殊表名需要解包
tableName = getPureTableName(tableName);
List<String> columnNames = null;
try {
try (final ResultSet rs = this.raw.getColumns(catalog, schema, tableName, null)) {
if (null != rs) {
columnNames = new ArrayList<>(rs.getFetchSize());
while (rs.next()) {
columnNames.add(rs.getString("COLUMN_NAME"));
}
}
}
return (CollUtil.isEmpty(columnNames)) ? new String[0] :columnNames.toArray(new String[0]);
} catch (final Exception e) {
throw new DbException("Get columns error!", e);
}
}
/** /**
* 从数据库元数据中获取指定表的列信息 * 从数据库元数据中获取指定表的列信息
* *

View File

@ -13,7 +13,6 @@
package org.dromara.hutool.db.meta; package org.dromara.hutool.db.meta;
import org.dromara.hutool.core.collection.ListUtil; import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.convert.Convert;
import org.dromara.hutool.core.io.IoUtil; import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.db.DbException; import org.dromara.hutool.db.DbException;
@ -21,7 +20,6 @@ import org.dromara.hutool.db.Entity;
import javax.sql.DataSource; import javax.sql.DataSource;
import java.sql.*; import java.sql.*;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -39,14 +37,17 @@ import java.util.Set;
* @author looly * @author looly
*/ */
public class MetaUtil { public class MetaUtil {
// region ----- getTableNames
/** /**
* 获得所有表名 * 获得所有表名
* *
* @param ds 数据源 * @param ds 数据源
* @return 表名列表 * @return 表名列表
*/ */
public static List<String> getTables(final DataSource ds) { public static List<String> getTableNames(final DataSource ds) {
return getTables(ds, TableType.TABLE); return getTableNames(ds, TableType.TABLE);
} }
/** /**
@ -56,8 +57,8 @@ public class MetaUtil {
* @param types 表类型 * @param types 表类型
* @return 表名列表 * @return 表名列表
*/ */
public static List<String> getTables(final DataSource ds, final TableType... types) { public static List<String> getTableNames(final DataSource ds, final TableType... types) {
return getTables(ds, null, null, types); return getTableNames(ds, null, null, types);
} }
/** /**
@ -69,8 +70,8 @@ public class MetaUtil {
* @return 表名列表 * @return 表名列表
* @since 3.3.1 * @since 3.3.1
*/ */
public static List<String> getTables(final DataSource ds, final String schema, final TableType... types) { public static List<String> getTableNames(final DataSource ds, final String schema, final TableType... types) {
return getTables(ds, schema, null, types); return getTableNames(ds, schema, null, types);
} }
/** /**
@ -78,42 +79,48 @@ public class MetaUtil {
* *
* @param ds 数据源 * @param ds 数据源
* @param schema 表数据库名对于Oracle为用户名 * @param schema 表数据库名对于Oracle为用户名
* @param tableName 表名 * @param tableNamePattern 表名匹配模式
* @param types 表类型 * @param types 表类型
* @return 表名列表 * @return 表名列表
* @since 3.3.1 * @since 3.3.1
*/ */
public static List<String> getTables(final DataSource ds, String schema, final String tableName, final TableType... types) { public static List<String> getTableNames(final DataSource ds, String schema, final String tableNamePattern, final TableType... types) {
final List<String> tables = new ArrayList<>(); return getTableNames(ds, null, schema, tableNamePattern, types);
}
/**
* 获得所有表名
*
* @param ds 数据源
* @param schema 表数据库名对于Oracle为用户名
* @param tableNamePattern 表名匹配模式
* @param types 表类型
* @return 表名列表
* @since 3.3.1
*/
public static List<String> getTableNames(final DataSource ds, String catalog, String schema, final String tableNamePattern, final TableType... types) {
Connection conn = null; Connection conn = null;
try { try {
conn = ds.getConnection(); conn = ds.getConnection();
// catalog和schema获取失败默认使用null代替 // catalog和schema获取失败默认使用null代替
final String catalog = getCatalog(conn); if(null == schema){
catalog = getCatalog(conn);
}
if (null == schema) { if (null == schema) {
schema = getSchema(conn); schema = getSchema(conn);
} }
final DatabaseMetaData metaData = conn.getMetaData(); return DatabaseMetaDataWrapper.of(conn.getMetaData(), catalog, schema).getTableNames(tableNamePattern, types);
try (final ResultSet rs = metaData.getTables(catalog, schema, tableName, Convert.toStrArray(types))) {
if (null != rs) {
String table;
while (rs.next()) {
table = rs.getString("TABLE_NAME");
if (StrUtil.isNotBlank(table)) {
tables.add(table);
}
}
}
}
} catch (final Exception e) { } catch (final Exception e) {
throw new DbException("Get tables error!", e); throw new DbException("Get tables error!", e);
} finally { } finally {
IoUtil.closeQuietly(conn); IoUtil.closeQuietly(conn);
} }
return tables;
} }
// endregion
// region ----- getColumnNames
/** /**
* 获得结果集的所有列名 * 获得结果集的所有列名
@ -123,15 +130,31 @@ public class MetaUtil {
* @throws DbException SQL执行异常 * @throws DbException SQL执行异常
*/ */
public static String[] getColumnNames(final ResultSet rs) throws DbException { public static String[] getColumnNames(final ResultSet rs) throws DbException {
final ResultSetMetaData metaData;
try { try {
final ResultSetMetaData rsmd = rs.getMetaData(); metaData = rs.getMetaData();
final int columnCount = rsmd.getColumnCount(); } catch (final SQLException e) {
throw new DbException(e);
}
return getColumnNames(metaData);
}
/**
* 获得结果集的所有列名
*
* @param metaData {@link ResultSetMetaData}
* @return 列名数组
* @throws DbException SQL执行异常
*/
public static String[] getColumnNames(final ResultSetMetaData metaData) throws DbException {
try {
final int columnCount = metaData.getColumnCount();
final String[] labelNames = new String[columnCount]; final String[] labelNames = new String[columnCount];
for (int i = 0; i < labelNames.length; i++) { for (int i = 0; i < labelNames.length; i++) {
labelNames[i] = rsmd.getColumnLabel(i + 1); labelNames[i] = metaData.getColumnLabel(i + 1);
} }
return labelNames; return labelNames;
} catch (final Exception e) { } catch (final SQLException e) {
throw new DbException("Get colunms error!", e); throw new DbException("Get colunms error!", e);
} }
} }
@ -145,30 +168,17 @@ public class MetaUtil {
* @throws DbException SQL执行异常 * @throws DbException SQL执行异常
*/ */
public static String[] getColumnNames(final DataSource ds, final String tableName) { public static String[] getColumnNames(final DataSource ds, final String tableName) {
final List<String> columnNames = new ArrayList<>();
Connection conn = null; Connection conn = null;
try { try {
conn = ds.getConnection(); conn = ds.getConnection();
return DatabaseMetaDataWrapper.of(conn).getColumnNames(tableName);
// catalog和schema获取失败默认使用null代替
final String catalog = getCatalog(conn);
final String schema = getSchema(conn);
final DatabaseMetaData metaData = conn.getMetaData();
try (final ResultSet rs = metaData.getColumns(catalog, schema, tableName, null)) {
if (null != rs) {
while (rs.next()) {
columnNames.add(rs.getString("COLUMN_NAME"));
}
}
}
return columnNames.toArray(new String[0]);
} catch (final Exception e) { } catch (final Exception e) {
throw new DbException("Get columns error!", e); throw new DbException("Get columns error!", e);
} finally { } finally {
IoUtil.closeQuietly(conn); IoUtil.closeQuietly(conn);
} }
} }
// endregion
/** /**
* 创建带有字段限制的Entity对象<br> * 创建带有字段限制的Entity对象<br>

View File

@ -32,8 +32,8 @@ public class MetaUtilTest {
final DataSource ds = DSUtil.getDS("test"); final DataSource ds = DSUtil.getDS("test");
@Test @Test
public void getTablesTest() { public void getTableNamesTest() {
final List<String> tables = MetaUtil.getTables(ds); final List<String> tables = MetaUtil.getTableNames(ds);
Assertions.assertTrue(tables.contains("user")); Assertions.assertTrue(tables.contains("user"));
} }