支持达梦数据库

This commit is contained in:
SanLi
2020-09-18 13:56:04 +08:00
parent 11d58b1dc3
commit a622bdd006
8 changed files with 571 additions and 16 deletions

BIN
lib/Dm7JdbcDriver-16.jar Normal file

Binary file not shown.

View File

@@ -19,7 +19,6 @@ package cn.smallbun.screw.core.query;
import cn.smallbun.screw.core.query.cachedb.CacheDbDataBaseQuery;
import cn.smallbun.screw.core.query.db2.Db2DataBaseQuery;
import cn.smallbun.screw.core.query.dm.DmDataBaseQuery;
import cn.smallbun.screw.core.query.h2.H2DataBaseQuery;
import cn.smallbun.screw.core.query.highgo.HigHgoDataBaseQuery;
import cn.smallbun.screw.core.query.hsql.HsqlDataBaseQuery;

View File

@@ -17,27 +17,94 @@
*/
package cn.smallbun.screw.core.query.dm;
import static cn.smallbun.screw.core.constant.DefaultConstants.PERCENT_SIGN;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
import javax.sql.DataSource;
import cn.smallbun.screw.core.exception.QueryException;
import cn.smallbun.screw.core.mapping.Mapping;
import cn.smallbun.screw.core.metadata.Column;
import cn.smallbun.screw.core.metadata.Database;
import cn.smallbun.screw.core.metadata.PrimaryKey;
import cn.smallbun.screw.core.metadata.Table;
import cn.smallbun.screw.core.query.AbstractDatabaseQuery;
import cn.smallbun.screw.core.query.dm.model.DmColumnModel;
import cn.smallbun.screw.core.query.dm.model.DmDatabaseModel;
import cn.smallbun.screw.core.query.dm.model.DmPrimaryKeyModel;
import cn.smallbun.screw.core.query.dm.model.DmTableModel;
import cn.smallbun.screw.core.util.Assert;
import cn.smallbun.screw.core.util.CollectionUtils;
import cn.smallbun.screw.core.util.ExceptionUtils;
import javax.sql.DataSource;
import java.util.List;
import static cn.smallbun.screw.core.constant.DefaultConstants.NOT_SUPPORTED;
import cn.smallbun.screw.core.util.JdbcUtils;
import dm.jdbc.driver.DmdbConnection;
/**
* 达梦数据库查询
*
* @author SanLi
* Created by qinggang.zuo@gmail.com / 2689170096@qq.com on 2020/3/20 17:40
* Created by jincy@neusoft.com + qinggang.zuo@gmail.com / 2689170096@qq.com on 2020/9/17 17:40
*/
@SuppressWarnings("serial")
public class DmDataBaseQuery extends AbstractDatabaseQuery {
private ConcurrentMap<String, List<DmTableModel>> tablesMap = new ConcurrentHashMap<>();
private static String DM_QUERY_TABLE_SQL = ""
+ "select "
+ " ut.table_name TABLE_NAME, "
+ " utc.comments COMMENTS "
+ "from "
+ " user_tables ut "
+ "left join USER_TAB_COMMENTS utc "
+ "on "
+ " ut.table_name=utc.table_name ";
private static String DM_QUERY_COLUMNS_SQL = "" + "select "
+ " ut.table_name TABLE_NAME , "
+ " uc.column_name COLUMN_NAME , "
//+ " case uc.data_type when 'INT' then uc.data_type when 'CLOB' then uc.data_type when 'BLOB' then uc.data_type when 'INTEGER' then uc.data_type else concat(concat(concat(uc.data_type, '('), uc.data_length), ')') end case AS COLUMN_TYPE , "
+ " case uc.data_type when 'CLOB' then uc.data_type when 'BLOB' then uc.data_type else concat(concat(concat(uc.data_type, '('), uc.data_length), ')') end case AS COLUMN_TYPE , "
+ " uc.data_length COLUMN_LENGTH , "
+ " uc.DATA_PRECISION DATA_PRECISION, "
+ " uc.DATA_SCALE DECIMAL_DIGITS, "
+ " case uc.NULLABLE when 'Y' then '1' else '0' end case NULLABLE,"
+ " uc.DATA_DEFAULT COLUMN_DEF, "
+ " ucc.comments REMARKS "
+ "from "
+ " user_tables ut "
+ "left join USER_TAB_COMMENTS utc "
+ "on "
+ " ut.table_name=utc.table_name "
+ "left join user_tab_columns uc "
+ "on "
+ " ut.table_name=uc.table_name "
+ "left join user_col_comments ucc "
+ "on "
+ " uc.table_name =ucc.table_name "
+ " and uc.column_name=ucc.column_name "
+ "where 1=1 ";
private static String DM_QUERY_PK_SQL = "" + "SELECT "
+ "C.OWNER AS TABLE_SCHEM, "
+ "C.TABLE_NAME , "
+ "C.COLUMN_NAME , "
+ "C.POSITION AS KEY_SEQ , "
+ "C.CONSTRAINT_NAME AS PK_NAME "
+ "FROM "
+ " ALL_CONS_COLUMNS C, "
+ " ALL_CONSTRAINTS K "
+ "WHERE "
+ " K.CONSTRAINT_TYPE = 'P' "
+ " AND K.OWNER = '%s' "
+ " AND K.CONSTRAINT_NAME = C.CONSTRAINT_NAME "
+ " AND K.TABLE_NAME = C.TABLE_NAME "
+ " AND K.OWNER = C.OWNER ";
/**
* 构造函数
@@ -55,7 +122,46 @@ public class DmDataBaseQuery extends AbstractDatabaseQuery {
*/
@Override
public Database getDataBase() throws QueryException {
throw ExceptionUtils.mpe(NOT_SUPPORTED);
DmDatabaseModel model = new DmDatabaseModel();
//当前数据库名称
model.setDatabase(getSchema());
return model;
}
/**
* 获取达梦数据库的schema
*
* @return {@link String} 达梦数据库的schema信息
*/
@Override
public String getSchema() throws QueryException {
try {
String schema;
DmdbConnection conn = (DmdbConnection) getMetaData().getConnection();
schema = conn.getUserName();
return schema;
} catch (SQLException e) {
throw ExceptionUtils.mpe(e);
}
}
/**
* 获取达梦数据库的schema
*
* @return {@link String} 达梦数据库的schema信息
*/
public String getSchemaBak() throws QueryException {
try {
String schema = null;
ResultSet rs = getMetaData().getSchemas();
while (rs.next()) {
schema = rs.getString(1);
break;
}
return schema;
} catch (Exception e) {
throw ExceptionUtils.mpe(e);
}
}
/**
@@ -64,8 +170,34 @@ public class DmDataBaseQuery extends AbstractDatabaseQuery {
* @return {@link List} 所有表信息
*/
@Override
public List<Table> getTables() {
throw ExceptionUtils.mpe(NOT_SUPPORTED);
public List<DmTableModel> getTables() throws QueryException {
ResultSet resultSet = null;
try {
//查询
resultSet = getMetaData().getTables(getSchema(), getSchema(), PERCENT_SIGN,
new String[] { "TABLE" });
//映射
List<DmTableModel> list = Mapping.convertList(resultSet, DmTableModel.class);
resultSet = prepareStatement(DM_QUERY_TABLE_SQL).executeQuery();
List<DmTableModel> inquires = Mapping.convertList(resultSet, DmTableModel.class);
//处理备注信息
list.forEach((DmTableModel model) -> {
//备注
inquires.stream()
.filter(inquire -> model.getTableName().equals(inquire.getTableName()))
.forEachOrdered(inquire -> model.setRemarks(inquire.getRemarks()));
});
if (!list.isEmpty()) {
tablesMap.put("AllTable", list);
}
return list;
} catch (SQLException e) {
throw ExceptionUtils.mpe(e);
} finally {
JdbcUtils.close(resultSet, this.connection);
}
}
/**
@@ -73,12 +205,52 @@ public class DmDataBaseQuery extends AbstractDatabaseQuery {
*
* @param table {@link String} 表名
* @return {@link List} 表字段信息
* @throws QueryException QueryException
*/
@Override
public List<Column> getTableColumns(String table) throws QueryException {
public List<DmColumnModel> getTableColumns(String table) throws QueryException {
Assert.notEmpty(table, "Table name can not be empty!");
throw ExceptionUtils.mpe(NOT_SUPPORTED);
ResultSet resultSet = null;
List<DmColumnModel> resultList = new ArrayList<>();
List<String> tableNames = new ArrayList<>();
try {
//从缓存中获取表对象
List<DmTableModel> tables = tablesMap.get("AllTable");
if (tables.isEmpty()) {
tables = getTables();
} else {
for (DmTableModel dtm : tables) {
tableNames.add(dtm.getTableName());
}
}
/*如果表为空,则直接返回*/
if (tableNames.isEmpty()) {
return null;
}
if (CollectionUtils.isEmpty(columnsCaching)) {
//查询全部
if (table.equals(PERCENT_SIGN)) {
PreparedStatement statement = prepareStatement(DM_QUERY_COLUMNS_SQL);
resultSet = statement.executeQuery();
} else {
//查询单表的列信息
String singleTableSql = DM_QUERY_COLUMNS_SQL.concat(" and ut.table_name='%s'");
resultSet = prepareStatement(String.format(singleTableSql, table))
.executeQuery();
}
List<DmColumnModel> inquires = Mapping.convertList(resultSet, DmColumnModel.class);
//这里利用lambda表达式将多行列信息按table name 进行归类,并放入缓存
tableNames.forEach(name -> columnsCaching.put(name, inquires.stream()
.filter(i -> i.getTableName().equals(name)).collect(Collectors.toList())));
resultList = inquires;
}
return resultList;
} catch (SQLException e) {
throw ExceptionUtils.mpe(e);
} finally {
JdbcUtils.close(resultSet, this.connection);
}
}
/**
@@ -89,7 +261,7 @@ public class DmDataBaseQuery extends AbstractDatabaseQuery {
*/
@Override
public List<? extends Column> getTableColumns() throws QueryException {
throw ExceptionUtils.mpe(NOT_SUPPORTED);
return getTableColumns(PERCENT_SIGN);
}
/**
@@ -101,7 +273,37 @@ public class DmDataBaseQuery extends AbstractDatabaseQuery {
*/
@Override
public List<? extends PrimaryKey> getPrimaryKeys(String table) throws QueryException {
throw ExceptionUtils.mpe(NOT_SUPPORTED);
ResultSet resultSet = null;
try {
//查询
resultSet = getMetaData().getPrimaryKeys(getSchema(), getSchema(), table);
//映射
return Mapping.convertList(resultSet, DmPrimaryKeyModel.class);
} catch (SQLException e) {
throw ExceptionUtils.mpe(e);
} finally {
JdbcUtils.close(resultSet, this.connection);
}
}
/**
* 根据表名获取主键
*
* @return {@link List}
* @throws QueryException QueryException
*/
@Override
public List<? extends PrimaryKey> getPrimaryKeys() throws QueryException {
ResultSet resultSet = null;
try {
// 由于单条循环查询存在性能问题所以这里通过自定义SQL查询数据库主键信息
String sql = String.format(DM_QUERY_PK_SQL, getSchema());
resultSet = prepareStatement(sql).executeQuery();
return Mapping.convertList(resultSet, DmPrimaryKeyModel.class);
} catch (SQLException e) {
throw new QueryException(e);
} finally {
JdbcUtils.close(resultSet);
}
}
}

View File

@@ -0,0 +1,177 @@
/*
* screw-core - 简洁好用的数据库表结构文档生成工具
* Copyright © 2020 SanLi (qinggang.zuo@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cn.smallbun.screw.core.query.dm.model;
import cn.smallbun.screw.core.mapping.MappingField;
import cn.smallbun.screw.core.metadata.Column;
import lombok.Data;
/**
* oracle table column
*
* @author SanLi
* Created by qinggang.zuo@gmail.com / 2689170096@qq.com on 2020/3/27 8:44
*/
@Data
public class DmColumnModel implements Column {
/**
* 表名称,它是引用属性的作用域(如果 DATA_TYPE 不是 REF则为 null
*/
@MappingField(value = "SCOPE_TABLE")
private Object scopeTable;
/**
* 表类别
*/
@MappingField(value = "TABLE_CAT")
private Object tableCat;
/**
* 未被使用
*/
@MappingField(value = "BUFFER_LENGTH")
private String bufferLength;
/**
* ISO 规则用于确定列是否包括 null。
*/
@MappingField(value = "IS_NULLABLE")
private String isNullable;
/**
* 数据源依赖的类型名称,对于 UDT该类型名称是完全限定的
*/
@MappingField(value = "TABLE_NAME")
private String tableName;
/**
* 该列的默认值,当值在单引号内时应被解释为一个字符串(可为 null
*/
@MappingField(value = "COLUMN_DEF")
private String columnDef;
/**
* 表的类别,它是引用属性的作用域(如果 DATA_TYPE 不是 REF则为 null
*/
@MappingField(value = "SCOPE_CATALOG")
private Object scopeCatalog;
/**
* 表模式
*/
@MappingField(value = "TABLE_SCHEM")
private String tableSchem;
/**
* 列名称
*/
@MappingField(value = "COLUMN_NAME")
private String columnName;
/**
* 是否允许使用 NULL。
*/
@MappingField(value = "NULLABLE")
private String nullable;
/**
* 描述列的注释(可为 null
*/
@MappingField(value = "REMARKS")
private String remarks;
/**
* 小数部分的位数。对于 DECIMAL_DIGITS 不适用的数据类型,则返回 Null。
*/
@MappingField(value = "DECIMAL_DIGITS")
private String decimalDigits;
/**
* 基数(通常为 10 或 2
*/
@MappingField(value = "NUM_PREC_RADIX")
private String numPrecRadix;
/**
*
*/
@MappingField(value = "SQL_DATETIME_SUB")
private String sqlDatetimeSub;
/**
*
*/
@MappingField(value = "IS_GENERATEDCOLUMN")
private String isGeneratedColumn;
/**
* 指示此列是否自动增加
* YES --- 如果该列自动增加
* NO --- 如果该列不自动增加
*/
@MappingField(value = "IS_AUTOINCREMENT")
private String isAutoIncrement;
/**
* SQL数据类型
*/
@MappingField(value = "SQL_DATA_TYPE")
private String sqlDataType;
/**
* 对于 char 类型,该长度是列中的最大字节数
*/
@MappingField(value = "CHAR_OCTET_LENGTH")
private String charOctetLength;
/**
* 表中的列的索引(从 1 开始)
*/
@MappingField(value = "ORDINAL_POSITION")
private String ordinalPosition;
/**
* 表的模式,它是引用属性的作用域(如果 DATA_TYPE 不是 REF则为 null
*/
@MappingField(value = "SCOPE_SCHEMA")
private String scopeSchema;
/**
* 不同类型或用户生成 Ref 类型、来自 java.sql.Types 的 SQL 类型的源类型(如果 DATA_TYPE 不是 DISTINCT 或用户生成的 REF则为 null
*/
@MappingField(value = "SOURCE_DATA_TYPE")
private String sourceDataType;
/**
* 来自 java.sql.Types 的 SQL 类型
*/
@MappingField(value = "DATA_TYPE")
private String dataType;
/**
* 数据源依赖的类型名称,对于 UDT该类型名称是完全限定的
*/
@MappingField(value = "TYPE_NAME")
private String typeName;
/**
* 列表示给定列的指定列大小。
* 对于数值数据,这是最大精度。
* 对于字符数据,这是字符长度。
* 对于日期时间数据类型,这是 String 表示形式的字符长度(假定允许的最大小数秒组件的精度)。
* 对于二进制数据,这是字节长度。
* 对于 ROWID 数据类型,这是字节长度。对于列大小不适用的数据类型,则返回 Null。
*/
@MappingField(value = "COLUMN_SIZE")
private String columnSize;
/**
* 是否主键
*/
private String primaryKey;
/**
* 列类型(带长度)
*/
@MappingField(value = "COLUMN_TYPE")
private String columnType;
/**
* 列长度
*/
@MappingField(value = "COLUMN_LENGTH")
private String columnLength;
}

View File

@@ -0,0 +1,39 @@
/*
* screw-core - 简洁好用的数据库表结构文档生成工具
* Copyright © 2020 SanLi (qinggang.zuo@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cn.smallbun.screw.core.query.dm.model;
import cn.smallbun.screw.core.mapping.MappingField;
import cn.smallbun.screw.core.metadata.Database;
import lombok.Data;
/**
* 数据库信息
*
* @author SanLi
* Created by qinggang.zuo@gmail.com / 2689170096@qq.com on 2020/3/17 20:26
*/
@Data
public class DmDatabaseModel implements Database {
private static final long serialVersionUID = 931210775266917894L;
/**
* 数据库名称
*/
@MappingField(value = "TABLE_CAT")
private String database;
}

View File

@@ -0,0 +1,58 @@
/*
* screw-core - 简洁好用的数据库表结构文档生成工具
* Copyright © 2020 SanLi (qinggang.zuo@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cn.smallbun.screw.core.query.dm.model;
import cn.smallbun.screw.core.mapping.MappingField;
import cn.smallbun.screw.core.metadata.PrimaryKey;
import lombok.Data;
/**
* oracle table primary
*
* @author SanLi
* Created by qinggang.zuo@gmail.com / 2689170096@qq.com on 2020/3/27 11:11
*/
@Data
public class DmPrimaryKeyModel implements PrimaryKey {
/**
* 表名
*/
@MappingField(value = "TABLE_NAME")
private String tableName;
/**
* pk name
*/
@MappingField(value = "PK_NAME")
private String pkName;
/**
* 表模式
*/
@MappingField(value = "TABLE_SCHEM")
private String tableSchem;
/**
* 列名
*/
@MappingField(value = "COLUMN_NAME")
private String columnName;
/**
* 键序列
*/
@MappingField(value = "KEY_SEQ")
private String keySeq;
}

View File

@@ -0,0 +1,57 @@
/*
* screw-core - 简洁好用的数据库表结构文档生成工具
* Copyright © 2020 SanLi (qinggang.zuo@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cn.smallbun.screw.core.query.dm.model;
import cn.smallbun.screw.core.mapping.MappingField;
import cn.smallbun.screw.core.metadata.Table;
import lombok.Data;
/**
* oracle table
*
* @author SanLi
* Created by qinggang.zuo@gmail.com / 2689170096@qq.com on 2020/3/27 8:44
*/
@Data
public class DmTableModel implements Table {
/**
* TABLE_CAT
*/
@MappingField(value = "TABLE_CAT")
private String tableCat;
/**
* 表名
*/
@MappingField(value = "TABLE_NAME")
private String tableName;
/**
* 表模式
*/
@MappingField(value = "TABLE_SCHEM")
private String tableSchem;
/**
* 表类型
*/
@MappingField(value = "TABLE_TYPE")
private String tableType;
/**
* 备注
*/
@MappingField(value = "REMARKS")
private String remarks;
}

View File

@@ -0,0 +1,23 @@
/*
* screw-core - 简洁好用的数据库表结构文档生成工具
* Copyright © 2020 SanLi (qinggang.zuo@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* DM Database query implement
* @author SanLi
* Created by qinggang.zuo@gmail.com / 2689170096@qq.com on 2020/6/19 16:00
*/
package cn.smallbun.screw.core.query.dm.model;