de/backend/src/main/java/io/dataease/datasource/provider/JdbcProvider.java
2021-07-01 15:08:57 +08:00

477 lines
21 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package io.dataease.datasource.provider;
import com.google.gson.Gson;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import io.dataease.datasource.constants.DatasourceTypes;
import io.dataease.datasource.dto.MysqlConfigration;
import io.dataease.datasource.dto.OracleConfigration;
import io.dataease.datasource.dto.SqlServerConfigration;
import io.dataease.datasource.dto.TableFiled;
import io.dataease.datasource.request.DatasourceRequest;
import io.dataease.exception.DataEaseException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.beans.PropertyVetoException;
import java.sql.*;
import java.util.*;
@Service("jdbc")
public class JdbcProvider extends DatasourceProvider {
private static Map<String, ComboPooledDataSource> jdbcConnection = new HashMap<>();
private static int initPoolSize = 1;
private static int maxConnections = 1;
/**
* 增加缓存机制 key 由 'provider_sql_' dsr.datasource.id dsr.table dsr.query共4部分组成命中则使用缓存直接返回不再执行sql逻辑
* @param dsr
* @return
* @throws Exception
*/
/**
* 这里使用声明式缓存不是很妥当
* 改为chartViewService中使用编程式缓存
@Cacheable(
value = JdbcConstants.JDBC_PROVIDER_KEY,
key = "'provider_sql_' + #dsr.datasource.id + '_' + #dsr.table + '_' + #dsr.query",
condition = "#dsr.pageSize == null || #dsr.pageSize == 0L"
)
*/
@Override
public List<String[]> getData(DatasourceRequest dsr) throws Exception {
List<String[]> list = new LinkedList<>();
Connection connection = null;
try {
connection = getConnectionFromPool(dsr);
Statement stat = connection.createStatement();
ResultSet rs = stat.executeQuery(dsr.getQuery());
list = fetchResult(rs);
} catch (SQLException e) {
DataEaseException.throwException(e);
} catch (Exception e) {
DataEaseException.throwException(e);
} finally {
if(connection != null){
connection.close();
}
}
return list;
}
public void exec(DatasourceRequest datasourceRequest) throws Exception {
Connection connection = null;
try {
connection = getConnectionFromPool(datasourceRequest);
Statement stat = connection.createStatement();
Boolean result = stat.execute(datasourceRequest.getQuery());
stat.close();
} catch (SQLException e) {
DataEaseException.throwException(e);
} catch (Exception e) {
DataEaseException.throwException(e);
} finally {
if(connection != null){
connection.close();
}
}
}
@Override
public List<String[]> fetchResult(DatasourceRequest datasourceRequest) throws Exception {
ResultSet rs;
Connection connection = null;
try {
connection = getConnectionFromPool(datasourceRequest);
Statement stat = connection.createStatement();
rs = stat.executeQuery(datasourceRequest.getQuery());
return fetchResult(rs);
} catch (SQLException e) {
DataEaseException.throwException(e);
} catch (Exception e) {
DataEaseException.throwException(e);
} finally {
if(connection != null){
connection.close();
}
}
return new ArrayList<>();
}
private List<String[]> fetchResult(ResultSet rs) throws Exception {
List<String[]> list = new LinkedList<>();
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
while (rs.next()) {
String[] row = new String[columnCount];
for (int j = 0; j < columnCount; j++) {
int columType = metaData.getColumnType(j + 1);
switch (columType) {
case Types.DATE:
row[j] = rs.getDate(j + 1).toString();
break;
default:
row[j] = rs.getString(j + 1);
break;
}
}
list.add(row);
}
return list;
}
@Override
public List<TableFiled> fetchResultField(DatasourceRequest datasourceRequest) throws Exception {
ResultSet rs;
Connection connection = null;
try {
connection = getConnectionFromPool(datasourceRequest);
Statement stat = connection.createStatement();
rs = stat.executeQuery(datasourceRequest.getQuery());
return fetchResultField(rs);
} catch (SQLException e) {
DataEaseException.throwException(e);
} catch (Exception e) {
DataEaseException.throwException(e);
} finally {
if(connection != null){
connection.close();
}
}
return new ArrayList<>();
}
@Override
public Map<String, List> fetchResultAndField(DatasourceRequest datasourceRequest) throws Exception {
ResultSet rs;
Map<String, List> result = new HashMap<>();
Connection connection = null;
List<String[]> dataList = new LinkedList<>();
List<TableFiled> fieldList = new ArrayList<>();
try {
connection = getConnectionFromPool(datasourceRequest);
Statement stat = connection.createStatement();
rs = stat.executeQuery(datasourceRequest.getQuery());
dataList = fetchResult(rs);
fieldList = fetchResultField(rs);
result.put("dataList", dataList);
result.put("fieldList", fieldList);
return result;
} catch (SQLException e) {
DataEaseException.throwException(e);
} catch (Exception e) {
DataEaseException.throwException(e);
} finally {
if(connection != null){
connection.close();
}
}
return new HashMap<>();
}
private List<TableFiled> fetchResultField(ResultSet rs) throws Exception {
List<TableFiled> fieldList = new ArrayList<>();
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
for (int j = 0; j < columnCount; j++) {
String f = metaData.getColumnName(j + 1);
String l = StringUtils.isNotEmpty(metaData.getColumnLabel(j + 1)) ? metaData.getColumnLabel(j + 1) : f;
String t = metaData.getColumnTypeName(j + 1);
TableFiled field = new TableFiled();
field.setFieldName(l);
field.setRemarks(l);
field.setFieldType(t);
field.setFieldSize(metaData.getColumnDisplaySize(j + 1));
if(t.equalsIgnoreCase("LONG")){field.setFieldSize(65533);} //oracle LONG
fieldList.add(field);
}
return fieldList;
}
@Override
public List<String> getTables(DatasourceRequest datasourceRequest) throws Exception {
List<String> tables = new ArrayList<>();
String queryStr = getTablesSql(datasourceRequest);
Connection con = null;
try {
con = getConnectionFromPool(datasourceRequest);
Statement statement = con.createStatement();
ResultSet resultSet = statement.executeQuery(queryStr);
while (resultSet.next()) {
tables.add(resultSet.getString(1));
}
resultSet.close();
statement.close();
return tables;
} catch (Exception e) {
DataEaseException.throwException(e);
} finally {
if(con != null){
con.close();
}
}
return new ArrayList<>();
}
@Override
public List<TableFiled> getTableFileds(DatasourceRequest datasourceRequest) throws Exception {
List<TableFiled> list = new LinkedList<>();
Connection connection = null;
try {
connection = getConnectionFromPool(datasourceRequest);
DatabaseMetaData databaseMetaData = connection.getMetaData();
ResultSet resultSet = databaseMetaData.getColumns(null, "%", datasourceRequest.getTable(), "%");
while (resultSet.next()) {
String tableName = resultSet.getString("TABLE_NAME");
String database = resultSet.getString("TABLE_CAT");
if(database != null){
if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDatabase(datasourceRequest))) {
TableFiled tableFiled = getTableFiled(resultSet);
list.add(tableFiled);
}
}else {
if (tableName.equals(datasourceRequest.getTable())) {
TableFiled tableFiled = getTableFiled(resultSet);
list.add(tableFiled);
}
}
}
resultSet.close();
} catch (SQLException e) {
DataEaseException.throwException(e);
} catch (Exception e) {
DataEaseException.throwException(e);
} finally {
if(connection != null){
connection.close();
}
}
return list;
}
private TableFiled getTableFiled(ResultSet resultSet) throws SQLException {
TableFiled tableFiled = new TableFiled();
String colName = resultSet.getString("COLUMN_NAME");
tableFiled.setFieldName(colName);
String remarks = resultSet.getString("REMARKS");
if (remarks == null || remarks.equals("")) {
remarks = colName;
}
tableFiled.setRemarks(remarks);
tableFiled.setFieldSize(Integer.valueOf(resultSet.getString("COLUMN_SIZE")));
String dbType = resultSet.getString("TYPE_NAME");
tableFiled.setFieldType(dbType);
if(dbType.equalsIgnoreCase("LONG")){tableFiled.setFieldSize(65533);}
if(StringUtils.isNotEmpty(dbType) && dbType.toLowerCase().contains("date") && tableFiled.getFieldSize() < 50 ){
tableFiled.setFieldSize(50);
}
return tableFiled;
}
@Override
public void test(DatasourceRequest datasourceRequest) throws Exception {
String queryStr = getTablesSql(datasourceRequest);
Connection con = null;
try {
con = getConnection(datasourceRequest);
Statement ps = con.createStatement();
ResultSet resultSet = ps.executeQuery(queryStr);
resultSet.close();
ps.close();
} catch (Exception e) {
DataEaseException.throwException(e);
} finally {
if(con != null){con.close();}
}
}
public Long count(DatasourceRequest datasourceRequest) throws Exception {
Connection con = null;
try {
con = getConnectionFromPool(datasourceRequest);
Statement ps = con.createStatement();
ResultSet resultSet = ps.executeQuery(datasourceRequest.getQuery());
while (resultSet.next()) {
return resultSet.getLong(1);
}
} catch (Exception e) {
DataEaseException.throwException( e);
} finally {
con.close();
}
return 0L;
}
private Connection getConnectionFromPool(DatasourceRequest datasourceRequest) throws Exception {
ComboPooledDataSource dataSource = jdbcConnection.get(datasourceRequest.getDatasource().getId());
if (dataSource == null) {
initDataSource(datasourceRequest, "add");
}
dataSource = jdbcConnection.get(datasourceRequest.getDatasource().getId());
Connection co = dataSource.getConnection();
return co;
}
@Override
public void initDataSource(DatasourceRequest datasourceRequest, String type) throws Exception {
switch (type){
case "add":
ComboPooledDataSource dataSource = jdbcConnection.get(datasourceRequest.getDatasource().getId());
if (dataSource == null) {
extracted(datasourceRequest);
}
break;
case "edit":
jdbcConnection.remove(datasourceRequest.getDatasource().getId());
extracted(datasourceRequest);
break;
case "delete":
jdbcConnection.remove(datasourceRequest.getDatasource().getId());
break;
default:
break;
}
}
private void extracted(DatasourceRequest datasourceRequest) throws PropertyVetoException {
ComboPooledDataSource dataSource;
dataSource = new ComboPooledDataSource();
setCredential(datasourceRequest, dataSource);
dataSource.setMaxIdleTime(30); // 最大空闲时间
dataSource.setAcquireIncrement(5);// 增长数
dataSource.setInitialPoolSize(initPoolSize);// 初始连接数
dataSource.setMinPoolSize(initPoolSize); // 最小连接数
dataSource.setMaxPoolSize(maxConnections); // 最大连接数
dataSource.setAcquireRetryAttempts(30);// 获取连接重试次数
dataSource.setIdleConnectionTestPeriod(60); // 每60s检查数据库空闲连接
dataSource.setMaxStatements(0); // c3p0全局的PreparedStatements缓存的大小
dataSource.setBreakAfterAcquireFailure(false); // 获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效保留并在下次调用getConnection()的时候继续尝试获取连接。如果设为true那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。Default: false
dataSource.setTestConnectionOnCheckout(false); // 在每个connection 提交是校验有效性
dataSource.setTestConnectionOnCheckin(true); // 取得连接的同时将校验连接的有效性
dataSource.setCheckoutTimeout(60000); // 从连接池获取连接的超时时间如设为0则无限期等待。单位毫秒默认为0
// dataSource.setPreferredTestQuery("SELECT 1");
dataSource.setDebugUnreturnedConnectionStackTraces(true);
dataSource.setUnreturnedConnectionTimeout(3600);
jdbcConnection.put(datasourceRequest.getDatasource().getId(), dataSource);
}
private static Connection getConnection(DatasourceRequest datasourceRequest) throws Exception {
String username = null;
String password = null;
String driver = null;
String jdbcurl = null;
DatasourceTypes datasourceType = DatasourceTypes.valueOf(datasourceRequest.getDatasource().getType());
switch (datasourceType) {
case mysql:
MysqlConfigration mysqlConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), MysqlConfigration.class);
username = mysqlConfigration.getUsername();
password = mysqlConfigration.getPassword();
driver = mysqlConfigration.getDriver();
jdbcurl = mysqlConfigration.getJdbc();
break;
case doris:
MysqlConfigration dorisConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), MysqlConfigration.class);
username = dorisConfigration.getUsername();
password = dorisConfigration.getPassword();
driver = dorisConfigration.getDriver();
jdbcurl = dorisConfigration.getJdbc();
break;
case sqlServer:
SqlServerConfigration sqlServerConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), SqlServerConfigration.class);
username = sqlServerConfigration.getUsername();
password = sqlServerConfigration.getPassword();
driver = sqlServerConfigration.getDriver();
jdbcurl = sqlServerConfigration.getJdbc();
break;
case oracle:
OracleConfigration oracleConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), OracleConfigration.class);
username = oracleConfigration.getUsername();
password = oracleConfigration.getPassword();
driver = oracleConfigration.getDriver();
jdbcurl = oracleConfigration.getJdbc();
break;
default:
break;
}
Class.forName(driver);
Properties props = new Properties();
props.setProperty("user", username);
if (StringUtils.isNotBlank(password)) {
props.setProperty("password", password);
}
return DriverManager.getConnection(jdbcurl, props);
}
private void setCredential(DatasourceRequest datasourceRequest, ComboPooledDataSource dataSource) throws PropertyVetoException {
DatasourceTypes datasourceType = DatasourceTypes.valueOf(datasourceRequest.getDatasource().getType());
switch (datasourceType) {
case mysql:
MysqlConfigration mysqlConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), MysqlConfigration.class);
dataSource.setUser(mysqlConfigration.getUsername());
dataSource.setDriverClass(mysqlConfigration.getDriver());
dataSource.setPassword(mysqlConfigration.getPassword());
dataSource.setJdbcUrl(mysqlConfigration.getJdbc());
break;
case doris:
MysqlConfigration dorisConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), MysqlConfigration.class);
dataSource.setUser(dorisConfigration.getUsername());
dataSource.setDriverClass(dorisConfigration.getDriver());
dataSource.setPassword(dorisConfigration.getPassword());
dataSource.setJdbcUrl(dorisConfigration.getJdbc());
break;
case sqlServer:
SqlServerConfigration sqlServerConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), SqlServerConfigration.class);
dataSource.setUser(sqlServerConfigration.getUsername());
dataSource.setDriverClass(sqlServerConfigration.getDriver());
dataSource.setPassword(sqlServerConfigration.getPassword());
dataSource.setJdbcUrl(sqlServerConfigration.getJdbc());
break;
case oracle:
OracleConfigration oracleConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), OracleConfigration.class);
dataSource.setUser(oracleConfigration.getUsername());
dataSource.setDriverClass(oracleConfigration.getDriver());
dataSource.setPassword(oracleConfigration.getPassword());
dataSource.setJdbcUrl(oracleConfigration.getJdbc());
break;
default:
break;
}
}
private String getDatabase(DatasourceRequest datasourceRequest) {
DatasourceTypes datasourceType = DatasourceTypes.valueOf(datasourceRequest.getDatasource().getType());
switch (datasourceType) {
case mysql:
MysqlConfigration mysqlConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), MysqlConfigration.class);
return mysqlConfigration.getDataBase();
case doris:
MysqlConfigration dorisConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), MysqlConfigration.class);
return dorisConfigration.getDataBase();
case sqlServer:
SqlServerConfigration sqlServerConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), SqlServerConfigration.class);
return sqlServerConfigration.getDataBase();
default:
return null;
}
}
private String getTablesSql(DatasourceRequest datasourceRequest) {
DatasourceTypes datasourceType = DatasourceTypes.valueOf(datasourceRequest.getDatasource().getType());
switch (datasourceType) {
case mysql:
return "show tables;";
case doris:
return "show tables;";
case sqlServer:
SqlServerConfigration sqlServerConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), SqlServerConfigration.class);
return "SELECT TABLE_NAME FROM DATABASE.INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE';".replace("DATABASE", sqlServerConfigration.getDataBase());
case oracle:
return "select TABLE_NAME from USER_TABLES";
default:
return "show tables;";
}
}
}