在我的 使用 JDBC API 获取 Mysql 的 表字段 时,返回为空 的解决方案 这篇Blog中,提及到了如何使用 JDBC API 来获取 column 的信息。
但是,当时没有讲到一个注意点,现在补充一下。
在 getColumns()
这个API中,它的4个参数的注释如下:
catalog - a catalog name; must match the catalog name as it is stored in the database; “” retrieves those without a catalog; null means that the catalog name should not be used to narrow the search
schemaPattern - a schema name pattern; must match the schema name as it is stored in the database; “” retrieves those without a schema; null means that the schema name should not be used to narrow the search
tableNamePattern - a table name pattern; must match the table name as it is stored in the database
columnNamePattern - a column name pattern; must match the column name as it is stored in the database
可以看到,后3个参数都是 pattern ,也就是说,这几个参数是支持通配符,即 支持 % 和 _ 来进行模糊匹配的。
所以,假设有如下的代码:
ResultSet colRet = dbMetaData.getColumns(null, "my%test", "tab002", "%");
那么,当你的数据库中,有 mytest 、my_test 、my1test、my23test 这些 schema 时,而这些 schema 中以恰巧都有一个名叫 tab002 的表时,那么,这些表中的这所有字段将会全部被返回。因为, % 是匹配任意多的字符的。
那么,问题来了?该如何对 % 和 _ 进行转义呢?
有些人会说,这还不简单么,直接用 ** 进行转义啊。
对,我一开始也是这么想的,但是事实总是残忍的。如果你当前使用的是 Oracle ,那么,很不幸的是,你这么做会导致你可能获取不到任何 column。
这是为什么呢?因为每个 数据库 提供商,他们在实现 JDBC 时,给定的转义符是不一样的,有的是 **,有的是 “\”。
那这咋整呢?不用急,细细找总是会有办法的。
果不其然,在 DatabaseMetaData 类中,提供了一个方法来获取转义字符,它就是 getSearchStringEscape()。所以,我们只需要对 schema 和 table 作如下的转义就可以了:
Connection connection = DriverManager.getConnection(jdbc_url, userName, password);
DatabaseMetaData dbMetaData = connection.getMetaData();
String escape = dbMetaData.getSearchStringEscape();
schema = schema.replace("_", (escape + "_"));
table = table.replace("%", (escape + "%"));
ResultSet colRet = dbMetaData.getColumns(null, schema, table, "%");
补充说明
虽然 catalog 这个参数没有声明是一个 pattern,但是通过对 mysql 的实验,其实它也是支持 pattern 的,所以,为了保险起见,我们最好对 catalog、schema、table 都做一个转义。
getTable() 这个API也需要一样的处理。
如有必要, getSchemas() 也需要同样的处理。