diff --git a/CHANGELOG.md b/CHANGELOG.md
index f50f7bb91..8223a282a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,7 @@
# 🚀Changelog
-------------------------------------------------------------------------------------------------------------
-# 5.7.23 (2022-03-16)
+# 5.7.23 (2022-03-17)
### 🐣新特性
* 【http 】 HttpRequest.form采用TableMap方式(issue#I4W427@Gitee)
@@ -18,6 +18,7 @@
* 【core 】 FileAppender优化初始List大小(pr#2197@Github)
* 【core 】 Base32增加pad支持(pr#2195@Github)
* 【core 】 Dict增加setFields方法(pr#578@Gitee)
+* 【db 】 新加db.meta的索引相关接口(pr#563@Gitee)
*
### 🐞Bug修复
* 【core 】 修复ObjectUtil.hasNull传入null返回true的问题(pr#555@Gitee)
diff --git a/hutool-db/src/main/java/cn/hutool/db/meta/Column.java b/hutool-db/src/main/java/cn/hutool/db/meta/Column.java
index 7faf402c1..b472bc3ea 100644
--- a/hutool-db/src/main/java/cn/hutool/db/meta/Column.java
+++ b/hutool-db/src/main/java/cn/hutool/db/meta/Column.java
@@ -1,7 +1,6 @@
package cn.hutool.db.meta;
import cn.hutool.core.util.BooleanUtil;
-import cn.hutool.core.util.StrUtil;
import cn.hutool.db.DbRuntimeException;
import java.io.Serializable;
@@ -93,7 +92,7 @@ public class Column implements Serializable, Cloneable {
try {
init(table, columnMetaRs);
} catch (SQLException e) {
- throw new DbRuntimeException(StrUtil.format("Get table [{}] meta info error!", tableName));
+ throw new DbRuntimeException(e, "Get table [{}] meta info error!", tableName);
}
}
// ----------------------------------------------------- Constructor end
diff --git a/hutool-db/src/main/java/cn/hutool/db/meta/ColumnIndexInfo.java b/hutool-db/src/main/java/cn/hutool/db/meta/ColumnIndexInfo.java
index 06404390d..d100cd208 100644
--- a/hutool-db/src/main/java/cn/hutool/db/meta/ColumnIndexInfo.java
+++ b/hutool-db/src/main/java/cn/hutool/db/meta/ColumnIndexInfo.java
@@ -1,24 +1,56 @@
package cn.hutool.db.meta;
+import cn.hutool.db.DbRuntimeException;
+
import java.io.Serializable;
+import java.sql.ResultSet;
+import java.sql.SQLException;
/**
* 索引中的列信息
*
* @author huzhongying
+ * @since 5.7.23
*/
-public class ColumnIndexInfo implements Serializable, Cloneable{
+public class ColumnIndexInfo implements Serializable, Cloneable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 根据DatabaseMetaData#getIndexInfo获取的{@link ResultSet}构建索引列信息
+ *
+ * @param rs 结果集,通过DatabaseMetaData#getIndexInfo获取
+ * @return ColumnIndexInfo
+ */
+ public static ColumnIndexInfo create(ResultSet rs) {
+ try {
+ return new ColumnIndexInfo(
+ rs.getString("COLUMN_NAME"),
+ rs.getString("ASC_OR_DESC"));
+ } catch (SQLException e) {
+ throw new DbRuntimeException(e);
+ }
+ }
/**
* 列名
*/
private String columnName;
-
/**
* 列排序顺序,“A”: 升序,“D” : 降序,如果不支持排序顺序,可能为空
*/
private String ascOrDesc;
+ /**
+ * 构造
+ *
+ * @param columnName 索引列名
+ * @param ascOrDesc 正序或反序,null表示无顺序表示
+ */
+ public ColumnIndexInfo(String columnName, String ascOrDesc) {
+ this.columnName = columnName;
+ this.ascOrDesc = ascOrDesc;
+ }
+
public String getColumnName() {
return columnName;
}
@@ -34,4 +66,17 @@ public class ColumnIndexInfo implements Serializable, Cloneable{
public void setAscOrDesc(String ascOrDesc) {
this.ascOrDesc = ascOrDesc;
}
+
+ @Override
+ public ColumnIndexInfo clone() throws CloneNotSupportedException {
+ return (ColumnIndexInfo) super.clone();
+ }
+
+ @Override
+ public String toString() {
+ return "ColumnIndexInfo{" +
+ "columnName='" + columnName + '\'' +
+ ", ascOrDesc='" + ascOrDesc + '\'' +
+ '}';
+ }
}
diff --git a/hutool-db/src/main/java/cn/hutool/db/meta/IndexInfo.java b/hutool-db/src/main/java/cn/hutool/db/meta/IndexInfo.java
index d3a3a142c..dd2cfb271 100644
--- a/hutool-db/src/main/java/cn/hutool/db/meta/IndexInfo.java
+++ b/hutool-db/src/main/java/cn/hutool/db/meta/IndexInfo.java
@@ -1,16 +1,21 @@
package cn.hutool.db.meta;
+import cn.hutool.core.util.ObjectUtil;
+
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
- * 数据库表的索引信息
+ * 数据库表的索引信息
+ * 如果时单列索引,只有一个{@link ColumnIndexInfo},联合索引则拥有多个{@link ColumnIndexInfo}
*
* @author huzhongying
*/
-public class IndexInfo implements Serializable, Cloneable{
+public class IndexInfo implements Serializable, Cloneable {
+ private static final long serialVersionUID = 1L;
/**
* 索引值是否可以不唯一
@@ -41,6 +46,24 @@ public class IndexInfo implements Serializable, Cloneable{
*/
private List columnIndexInfoList;
+ /**
+ * 构造
+ *
+ * @param nonUnique 索引值是否可以不唯一
+ * @param indexName 索引名称
+ * @param tableName 表名
+ * @param schema table所在的schema
+ * @param catalog table所在的catalog
+ */
+ public IndexInfo(boolean nonUnique, String indexName, String tableName, String schema, String catalog) {
+ this.nonUnique = nonUnique;
+ this.indexName = indexName;
+ this.tableName = tableName;
+ this.schema = schema;
+ this.catalog = catalog;
+ this.setColumnIndexInfoList(new ArrayList<>());
+ }
+
public boolean isNonUnique() {
return nonUnique;
}
@@ -89,21 +112,38 @@ public class IndexInfo implements Serializable, Cloneable{
this.columnIndexInfoList = columnIndexInfoList;
}
- /**
- *
- * @param nonUnique 索引值是否可以不唯一
- * @param indexName 索引名称
- * @param tableName 表名
- * @param schema table所在的schema
- * @param catalog table所在的catalog
- */
- public IndexInfo(boolean nonUnique, String indexName, String tableName, String schema, String catalog) {
- this.nonUnique = nonUnique;
- this.indexName = indexName;
- this.tableName = tableName;
- this.schema = schema;
- this.catalog = catalog;
- this.setColumnIndexInfoList(new ArrayList<>());
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ IndexInfo indexInfo = (IndexInfo) o;
+ return ObjectUtil.equals(indexName, indexInfo.indexName)
+ && ObjectUtil.equals(tableName, indexInfo.tableName);
}
+ @Override
+ public int hashCode() {
+ return Objects.hash(indexName, tableName);
+ }
+
+ @Override
+ public IndexInfo clone() throws CloneNotSupportedException {
+ return (IndexInfo) super.clone();
+ }
+
+ @Override
+ public String toString() {
+ return "IndexInfo{" +
+ "nonUnique=" + nonUnique +
+ ", indexName='" + indexName + '\'' +
+ ", tableName='" + tableName + '\'' +
+ ", schema='" + schema + '\'' +
+ ", catalog='" + catalog + '\'' +
+ ", columnIndexInfoList=" + columnIndexInfoList +
+ '}';
+ }
}
diff --git a/hutool-db/src/main/java/cn/hutool/db/meta/MetaUtil.java b/hutool-db/src/main/java/cn/hutool/db/meta/MetaUtil.java
index 85c3e85a3..bb151db76 100644
--- a/hutool-db/src/main/java/cn/hutool/db/meta/MetaUtil.java
+++ b/hutool-db/src/main/java/cn/hutool/db/meta/MetaUtil.java
@@ -2,7 +2,6 @@ package cn.hutool.db.meta;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
-import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.DbRuntimeException;
import cn.hutool.db.DbUtil;
@@ -83,7 +82,7 @@ public class MetaUtil {
conn = ds.getConnection();
// catalog和schema获取失败默认使用null代替
- String catalog = getCataLog(conn);
+ String catalog = getCatalog(conn);
if (null == schema) {
schema = getSchema(conn);
}
@@ -144,7 +143,7 @@ public class MetaUtil {
conn = ds.getConnection();
// catalog和schema获取失败默认使用null代替
- String catalog = getCataLog(conn);
+ String catalog = getCatalog(conn);
String schema = getSchema(conn);
final DatabaseMetaData metaData = conn.getMetaData();
@@ -202,8 +201,8 @@ public class MetaUtil {
*
* @param ds 数据源
* @param tableName 表名
- * @param catalog catalog name,{@code null}表示自动获取,见:{@link #getCataLog(Connection)}
- * @param schema a schema name pattern,{@code null}表示自动获取,见:{@link #getSchema(Connection)}
+ * @param catalog catalog name,{@code null}表示自动获取,见:{@link #getCatalog(Connection)}
+ * @param schema a schema name pattern,{@code null}表示自动获取,见:{@link #getSchema(Connection)}
* @return Table对象
* @since 5.7.22
*/
@@ -214,11 +213,11 @@ public class MetaUtil {
conn = ds.getConnection();
// catalog和schema获取失败默认使用null代替
- if(null == catalog){
- catalog = getCataLog(conn);
+ if (null == catalog) {
+ catalog = getCatalog(conn);
}
table.setCatalog(catalog);
- if(null == schema){
+ if (null == schema) {
schema = getSchema(conn);
}
table.setSchema(schema);
@@ -252,33 +251,30 @@ public class MetaUtil {
}
}
-
- // 获得索引信息
-
- try (ResultSet rs = metaData.getIndexInfo(catalog, schema, tableName, false,false)) {
- Map indexInfoMap = MapUtil.createMap(LinkedHashMap.class);
+ // 获得索引信息(since 5.7.23)
+ try (ResultSet rs = metaData.getIndexInfo(catalog, schema, tableName, false, false)) {
+ final Map indexInfoMap = new LinkedHashMap<>();
if (null != rs) {
while (rs.next()) {
//排除tableIndexStatistic类型索引
- if (rs.getShort("TYPE") != 0) {
- String indexName = rs.getString("INDEX_NAME");
- String key = StrUtil.join("&", tableName, indexName);
- IndexInfo indexInfo = indexInfoMap.getOrDefault(key
- , new IndexInfo(rs.getBoolean("NON_UNIQUE"),indexName,tableName,schema,catalog));
- ColumnIndexInfo columnIndexInfo = new ColumnIndexInfo();
- columnIndexInfo.setColumnName(rs.getString("COLUMN_NAME"));
- columnIndexInfo.setAscOrDesc(rs.getString("ASC_OR_DESC"));
- indexInfo.getColumnIndexInfoList().add(columnIndexInfo);
- if (!indexInfoMap.containsKey(key)) {
- indexInfoMap.put(key,indexInfo);
- }
-
+ if (0 == rs.getShort("TYPE")) {
+ continue;
}
+
+ final String indexName = rs.getString("INDEX_NAME");
+ final String key = StrUtil.join("&", tableName, indexName);
+ // 联合索引情况下一个索引会有多个列,此处须组合索引列到一个索引信息对象下
+ IndexInfo indexInfo = indexInfoMap.get(key);
+ if (null == indexInfo) {
+ indexInfo = new IndexInfo(rs.getBoolean("NON_UNIQUE"), indexName, tableName, schema, catalog);
+ indexInfoMap.put(key, indexInfo);
+ }
+ indexInfo.getColumnIndexInfoList().add(ColumnIndexInfo.create(rs));
}
}
table.setIndexInfoList(ListUtil.toList(indexInfoMap.values()));
}
- } catch (SQLException e) {
+ } catch (SQLException e) {
throw new DbRuntimeException("Get columns error!", e);
} finally {
DbUtil.close(conn);
@@ -293,8 +289,21 @@ public class MetaUtil {
* @param conn {@link Connection} 数据库连接,{@code null}时返回null
* @return catalog,获取失败返回{@code null}
* @since 4.6.0
+ * @deprecated 拼写错误,请使用{@link #getCatalog(Connection)}
*/
+ @Deprecated
public static String getCataLog(Connection conn) {
+ return getCatalog(conn);
+ }
+
+ /**
+ * 获取catalog,获取失败返回{@code null}
+ *
+ * @param conn {@link Connection} 数据库连接,{@code null}时返回null
+ * @return catalog,获取失败返回{@code null}
+ * @since 5.7.23
+ */
+ public static String getCatalog(Connection conn) {
if (null == conn) {
return null;
}
diff --git a/hutool-db/src/main/java/cn/hutool/db/meta/Table.java b/hutool-db/src/main/java/cn/hutool/db/meta/Table.java
index ae7b7e09b..7046b1284 100644
--- a/hutool-db/src/main/java/cn/hutool/db/meta/Table.java
+++ b/hutool-db/src/main/java/cn/hutool/db/meta/Table.java
@@ -1,7 +1,12 @@
package cn.hutool.db.meta;
import java.io.Serializable;
-import java.util.*;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
* 数据库表信息
@@ -31,11 +36,13 @@ public class Table implements Serializable, Cloneable {
* 主键字段名列表
*/
private Set pkNames = new LinkedHashSet<>();
-
/**
* 索引信息
*/
private List indexInfoList;
+ /**
+ * 列映射,列名-列对象
+ */
private final Map columns = new LinkedHashMap<>();
public static Table create(String tableName) {
@@ -154,7 +161,7 @@ public class Table implements Serializable, Cloneable {
* @return 是否为主键
* @since 5.4.3
*/
- public boolean isPk(String columnName){
+ public boolean isPk(String columnName) {
return getPkNames().contains(columnName);
}
@@ -213,13 +220,26 @@ public class Table implements Serializable, Cloneable {
/**
* 获取索引信息
+ *
* @return 索引信息
+ * @since 5.7.23
*/
public List getIndexInfoList() {
return indexInfoList;
}
+ /**
+ * 设置索引信息
+ *
+ * @param indexInfoList 索引信息列表
+ * @since 5.7.23
+ */
public void setIndexInfoList(List indexInfoList) {
this.indexInfoList = indexInfoList;
}
+
+ @Override
+ public Table clone() throws CloneNotSupportedException {
+ return (Table) super.clone();
+ }
}
diff --git a/hutool-db/src/main/java/cn/hutool/db/meta/TableType.java b/hutool-db/src/main/java/cn/hutool/db/meta/TableType.java
index 7c65bda4d..c22c084bc 100644
--- a/hutool-db/src/main/java/cn/hutool/db/meta/TableType.java
+++ b/hutool-db/src/main/java/cn/hutool/db/meta/TableType.java
@@ -2,35 +2,38 @@ package cn.hutool.db.meta;
/**
* 元信息中表的类型
- * @author Looly
*
+ * @author Looly
*/
public enum TableType {
TABLE("TABLE"),
VIEW("VIEW"),
- SYSTEM_TABLE ("SYSTEM TABLE"),
+ SYSTEM_TABLE("SYSTEM TABLE"),
GLOBAL_TEMPORARY("GLOBAL TEMPORARY"),
LOCAL_TEMPORARY("LOCAL TEMPORARY"),
ALIAS("ALIAS"),
SYNONYM("SYNONYM");
-
+
private final String value;
-
+
/**
* 构造
+ *
* @param value 值
*/
- TableType(String value){
+ TableType(String value) {
this.value = value;
}
+
/**
* 获取值
+ *
* @return 值
*/
- public String value(){
+ public String value() {
return this.value;
}
-
+
@Override
public String toString() {
return this.value();
diff --git a/hutool-db/src/main/java/cn/hutool/db/sql/Direction.java b/hutool-db/src/main/java/cn/hutool/db/sql/Direction.java
index 9e573093e..d8f1ee30c 100644
--- a/hutool-db/src/main/java/cn/hutool/db/sql/Direction.java
+++ b/hutool-db/src/main/java/cn/hutool/db/sql/Direction.java
@@ -4,23 +4,39 @@ import cn.hutool.core.util.StrUtil;
/**
* 排序方式(升序或者降序)
- * @author Looly
*
+ * @author Looly
*/
-public enum Direction{
- /** 升序 */
- ASC,
- /** 降序 */
- DESC;
-
+public enum Direction {
/**
- * 根据字符串值返回对应{@link Direction}值
- *
+ * 升序
+ */
+ ASC,
+ /**
+ * 降序
+ */
+ DESC;
+
+ /**
+ * 根据字符串值返回对应Direction值
+ *
* @param value 排序方式字符串,只能是 ASC或DESC
- * @return {@link Direction}
+ * @return Direction,{@code null}表示提供的value为空
* @throws IllegalArgumentException in case the given value cannot be parsed into an enum value.
*/
- public static Direction fromString(String value) throws IllegalArgumentException{
+ public static Direction fromString(String value) throws IllegalArgumentException {
+ if (StrUtil.isEmpty(value)) {
+ return null;
+ }
+
+ // 兼容元数据中ASC和DESC表示
+ if (1 == value.length()) {
+ if ("A".equalsIgnoreCase(value)) {
+ return ASC;
+ } else if ("D".equalsIgnoreCase(value)) {
+ return DESC;
+ }
+ }
try {
return Direction.valueOf(value.toUpperCase());
diff --git a/hutool-db/src/test/java/cn/hutool/db/meta/MetaUtilTest.java b/hutool-db/src/test/java/cn/hutool/db/meta/MetaUtilTest.java
index 4438c2a87..0abd88676 100644
--- a/hutool-db/src/test/java/cn/hutool/db/meta/MetaUtilTest.java
+++ b/hutool-db/src/test/java/cn/hutool/db/meta/MetaUtilTest.java
@@ -1,15 +1,13 @@
package cn.hutool.db.meta;
-import java.util.List;
-
-import javax.sql.DataSource;
-
-import org.junit.Assert;
-import org.junit.Test;
-
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.ds.DSFactory;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.sql.DataSource;
+import java.util.List;
/**
* 元数据信息单元测试