mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-05 17:37:59 +08:00
add meta index
This commit is contained in:
parent
ea8cfd6b54
commit
c500c43890
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
* 数据库表的索引信息
|
||||
* 数据库表的索引信息<br>
|
||||
* 如果时单列索引,只有一个{@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<ColumnIndexInfo> 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 +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@ -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<String, IndexInfo> indexInfoMap = MapUtil.createMap(LinkedHashMap.class);
|
||||
// 获得索引信息(since 5.7.23)
|
||||
try (ResultSet rs = metaData.getIndexInfo(catalog, schema, tableName, false, false)) {
|
||||
final Map<String, IndexInfo> 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;
|
||||
}
|
||||
|
@ -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<String> pkNames = new LinkedHashSet<>();
|
||||
|
||||
/**
|
||||
* 索引信息
|
||||
*/
|
||||
private List<IndexInfo> indexInfoList;
|
||||
/**
|
||||
* 列映射,列名-列对象
|
||||
*/
|
||||
private final Map<String, Column> 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<IndexInfo> getIndexInfoList() {
|
||||
return indexInfoList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置索引信息
|
||||
*
|
||||
* @param indexInfoList 索引信息列表
|
||||
* @since 5.7.23
|
||||
*/
|
||||
public void setIndexInfoList(List<IndexInfo> indexInfoList) {
|
||||
this.indexInfoList = indexInfoList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Table clone() throws CloneNotSupportedException {
|
||||
return (Table) super.clone();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
* 元数据信息单元测试
|
||||
|
Loading…
Reference in New Issue
Block a user