Commit 43dad422 by yuwei

项目初始化

parent fb67c15e
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>datax-common</artifactId>
<groupId>cn.datax</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>datax-common-database</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>${mariadb.version}</version>
</dependency>
<dependency>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>${oracle.version}</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>${sqlserver.version}</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package cn.datax.common.database;
import cn.datax.common.database.constants.DbQueryProperty;
public interface DataSourceFactory {
/**
* 创建数据源实例
*
* @param property
* @return
*/
DbQuery createDbQuery(DbQueryProperty property);
}
package cn.datax.common.database;
import cn.datax.common.database.core.DbColumn;
import org.springframework.jdbc.core.RowMapper;
/**
* 表数据查询接口
*
* @author yuwei
* @since 2020-03-14
*/
public interface DbDialect {
RowMapper<DbColumn> rowMapper();
/**
* 获取指定表的所有列
*
* @param tableName
* @return
*/
String columns(String tableName);
/**
* 获取数据库下的 所有表
*
* @param dbName
* @return
*/
String tables(String dbName);
/**
* 构建 分页 sql
*
* @param sql
* @param offset
* @param count
* @return
*/
String buildPaginationSql(String sql, long offset, long count);
/**
* 包装 count sql
*
* @param sql
* @return
*/
String count(String sql);
}
package cn.datax.common.database;
import cn.datax.common.database.core.DbColumn;
import cn.datax.common.database.core.PageResult;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
/**
* 表数据查询接口
*
* @author yuwei
* @since 2020-03-14
*/
public interface DbQuery {
/**
* 检测连通性
*/
boolean valid() throws SQLException;
/**
* 关闭数据源
*/
void close();
/**
* 获取指定表 具有的所有字段列表
* @param dbName
* @param tableName
* @return
*/
List<DbColumn> getTableColumns(String dbName, String tableName);
/**
* 获取指定数据库下 所有的表信息
*
* @param dbName
* @return
*/
List<String> getTables(String dbName);
/**
* 获取总数
*
* @param sql
* @return
*/
int count(String sql);
/**
* 查询结果列表
*
* @param sql
* @return
*/
List<Map<String, Object>> queryList(String sql);
/**
* 查询结果分页
*
* @param sql
* @param offset
* @param size
* @return
*/
PageResult<Map<String, Object>> queryByPage(String sql, long offset, long size);
}
package cn.datax.common.database;
import cn.datax.common.database.constants.DbType;
import cn.datax.common.database.dialect.DialectRegistry;
/**
* 方言工厂类
*
* @author yuwei
* @since 2020-03-14
*/
public class DialectFactory {
private static final DialectRegistry DIALECT_REGISTRY = new DialectRegistry();
public static DbDialect getDialect(DbType dbType) {
return DIALECT_REGISTRY.getDialect(dbType);
}
}
package cn.datax.common.database;
import cn.datax.common.database.constants.DbType;
import cn.datax.common.database.query.QueryRegistry;
public class QueryFactory {
private static final QueryRegistry QUERY_REGISTRY = new QueryRegistry();
public static DbQuery getQuery(DbType dbType) {
return QUERY_REGISTRY.getQuery(dbType);
}
}
package cn.datax.common.database.annotation;
import cn.datax.common.database.config.AutoConfiguration;
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({AutoConfiguration.class})
public @interface EnableDatabase {
}
package cn.datax.common.database.config;
import cn.datax.common.database.DataSourceFactory;
import cn.datax.common.database.datasource.CacheDataSourceFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
/**
* 扫描注入bean
*
* @author yuwei
* @since 2019/10/30
*/
@ComponentScan({"cn.datax.common.database"})
public class AutoConfiguration {
@Bean
public DataSourceFactory dataSourceFactory(){
return new CacheDataSourceFactoryBean();
}
}
package cn.datax.common.database.constants;
import cn.datax.common.database.exception.DataQueryException;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.util.StringUtils;
import java.io.Serializable;
@Data
@AllArgsConstructor
public class DbQueryProperty implements Serializable {
private static final long serialVersionUID = 1L;
private String dbType;
private String host;
private String username;
private String password;
private Integer port;
private String dbName;
/**
* 参数合法性校验
*/
public void viald() {
if (StringUtils.isEmpty(dbType) || StringUtils.isEmpty(host) ||
StringUtils.isEmpty(username) || StringUtils.isEmpty(password) ||
StringUtils.isEmpty(port) || StringUtils.isEmpty(dbName)) {
throw new DataQueryException("参数不完整");
}
if (DbType.OTHER.getDb().equals(dbType)) {
throw new DataQueryException("不支持的数据库类型");
}
}
}
package cn.datax.common.database.constants;
/**
* 数据库类型
*
* @author yuwei
* @since 2020-03-14
*/
public enum DbType {
/**
* MYSQL
*/
MYSQL("mysql", "MySql数据库", "jdbc:mysql://${host}:${port}/${dbName}?serverTimezone=GMT%2B8&characterEncoding=UTF-8&useUnicode=true&useSSL=false"),
/**
* MARIADB
*/
MARIADB("mariadb", "MariaDB数据库", "jdbc:mariadb://${host}:${port}/${dbName}"),
/**
* ORACLE
*/
ORACLE("oracle", "Oracle11g及以下数据库", "jdbc:oracle:thin:@${host}:${port}:${dbName}"),
/**
* oracle12c new pagination
*/
ORACLE_12C("oracle12c", "Oracle12c+数据库", "jdbc:oracle:thin:@${host}:${port}:${dbName}"),
/**
* POSTGRE
*/
POSTGRE_SQL("postgresql", "Postgre数据库", "jdbc:postgresql://${host}:${port}/${dbName}"),
/**
* SQLSERVER2005
*/
SQL_SERVER2008("sqlserver2008", "SQLServer2008及以下数据库", "jdbc:sqlserver://${host}:${port};DatabaseName=${dbName}"),
/**
* SQLSERVER
*/
SQL_SERVER("sqlserver", "SQLServer2012+数据库", "jdbc:sqlserver://${host}:${port};DatabaseName=${dbName}"),
/**
* UNKONWN DB
*/
OTHER("other", "其他数据库", "");
/**
* 数据库名称
*/
private final String db;
/**
* 描述
*/
private final String desc;
/**
* url
*/
private final String url;
public String getDb() {
return this.db;
}
public String getDesc() {
return this.desc;
}
public String getUrl() {
return this.url;
}
DbType(String db, String desc, String url) {
this.db = db;
this.desc = desc;
this.url = url;
}
/**
* 获取数据库类型
*
* @param dbType 数据库类型字符串
*/
public static DbType getDbType(String dbType) {
for (DbType type : DbType.values()) {
if (type.db.equalsIgnoreCase(dbType)) {
return type;
}
}
return OTHER;
}
}
package cn.datax.common.database.core;
import lombok.Data;
@Data
public class DbColumn {
private String name;
private String type;
private String length;
private String nullable;
private String hasKey;
}
package cn.datax.common.database.core;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
@Data
@Accessors(chain = true)
public class PageResult<T> implements Serializable {
private static final long serialVersionUID = 1L;
private long pageNum;
private long pageSize;
private long total;
private List<T> data;
public PageResult(long total, List<T> data) {
this.total = total;
this.data = data;
}
}
package cn.datax.common.database.datasource;
import cn.datax.common.database.*;
import cn.datax.common.database.constants.DbQueryProperty;
import cn.datax.common.database.constants.DbType;
import cn.datax.common.database.exception.DataQueryException;
import cn.datax.common.database.query.AbstractDbQuery;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.StringUtils;
import javax.sql.DataSource;
public abstract class AbstractDataSourceFactory implements DataSourceFactory {
@Override
public DbQuery createDbQuery(DbQueryProperty property) {
property.viald();
DbType dbType = DbType.getDbType(property.getDbType());
DataSource dataSource = createDataSource(property);
DbQuery dbQuery = createDbQueryTemplate(dataSource, dbType);
return dbQuery;
}
public DbQuery createDbQueryTemplate(DataSource dataSource, DbType dbType) {
DbDialect dbDialect = DialectFactory.getDialect(dbType);
AbstractDbQuery dbQuery = (AbstractDbQuery) QueryFactory.getQuery(dbType);
if(dbQuery == null){
throw new DataQueryException("该数据库类型正在开发中");
}
dbQuery.setDataSource(dataSource);
dbQuery.setJdbcTemplate(new JdbcTemplate(dataSource));
dbQuery.setDbDialect(dbDialect);
return dbQuery;
}
public DataSource createDataSource(DbQueryProperty property) {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(trainToJdbcUrl(property));
dataSource.setUsername(property.getUsername());
dataSource.setPassword(property.getPassword());
return dataSource;
}
protected String trainToJdbcUrl(DbQueryProperty property) {
String url = DbType.getDbType(property.getDbType()).getUrl();
if (StringUtils.isEmpty(url)) {
throw new DataQueryException("无效数据库类型!");
}
url = url.replace("${host}", property.getHost());
url = url.replace("${port}", String.valueOf(property.getPort()));
if (null == property.getDbName()){
property.setDbName("");
}
url = url.replace("${dbName}", property.getDbName());
return url;
}
}
package cn.datax.common.database.datasource;
import cn.datax.common.database.constants.DbQueryProperty;
import javax.sql.DataSource;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class CacheDataSourceFactoryBean extends AbstractDataSourceFactory {
/**
* 数据源缓存
*/
private static Map<String, DataSource> dataSourceMap = new ConcurrentHashMap<>();
@Override
public DataSource createDataSource(DbQueryProperty property) {
String key = property.getHost() + ":" + property.getPort() + ":" + property.getUsername()+ ":" + property.getDbName();
String s = compress(key);
DataSource dataSource = dataSourceMap.get(s);
if (null == dataSource) {
synchronized (CacheDataSourceFactoryBean.class) {
if (null == dataSource) {
dataSource = super.createDataSource(property);
dataSourceMap.put(s, dataSource);
}
}
}
return dataSource;
}
// 压缩
public static String compress(String str) {
if (str == null || str.length() == 0) {
return str;
}
MessageDigest md = null;
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
md.update(str.getBytes());
byte b[] = md.digest();
int i;
StringBuffer buf = new StringBuffer();
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
// System.out.println("MD5(" + str + ",32小写) = " + buf.toString());
// System.out.println("MD5(" + str + ",32大写) = " + buf.toString().toUpperCase());
// System.out.println("MD5(" + str + ",16小写) = " + buf.toString().substring(8, 24));
// System.out.println("MD5(" + str + ",16大写) = " + buf.toString().substring(8, 24).toUpperCase());
return buf.toString().substring(8, 24).toUpperCase();
}
}
package cn.datax.common.database.datasource;
public class DefaultDataSourceFactoryBean extends AbstractDataSourceFactory {
}
package cn.datax.common.database.dialect;
import cn.datax.common.database.DbDialect;
/**
* 方言抽象类
*
* @author yuwei
* @since 2020-03-14
*/
public abstract class AbstractDbDialect implements DbDialect {
@Override
public String columns(String tableName) {
return "show columns from `" + tableName + "`;";
}
@Override
public String tables(String dbName) {
return "show tables";
}
@Override
public String buildPaginationSql(String originalSql, long offset, long count) {
// 获取 分页实际条数
StringBuilder sqlBuilder = new StringBuilder(originalSql);
sqlBuilder.append(" LIMIT ").append(offset).append(" , ").append(count);
return sqlBuilder.toString();
}
@Override
public String count(String sql) {
return "SELECT COUNT(*) FROM ( " + sql + " ) TEMP";
}
}
package cn.datax.common.database.dialect;
import cn.datax.common.database.DbDialect;
import cn.datax.common.database.constants.DbType;
import java.util.EnumMap;
import java.util.Map;
public class DialectRegistry {
private final Map<DbType, DbDialect> dialect_enum_map = new EnumMap<>(DbType.class);
public DialectRegistry() {
dialect_enum_map.put(DbType.MARIADB, new MariaDBDialect());
dialect_enum_map.put(DbType.MYSQL, new MySqlDialect());
dialect_enum_map.put(DbType.ORACLE_12C, new Oracle12cDialect());
dialect_enum_map.put(DbType.ORACLE, new OracleDialect());
dialect_enum_map.put(DbType.POSTGRE_SQL, new PostgreDialect());
dialect_enum_map.put(DbType.SQL_SERVER2008, new SQLServer2008Dialect());
dialect_enum_map.put(DbType.SQL_SERVER, new SQLServerDialect());
dialect_enum_map.put(DbType.OTHER, new UnknownDialect());
}
public DbDialect getDialect(DbType dbType) {
return dialect_enum_map.get(dbType);
}
}
package cn.datax.common.database.dialect;
/**
* MariaDB 数据库方言
*
* @author yuwei
* @since 2020-03-14
*/
public class MariaDBDialect extends MySqlDialect {
}
package cn.datax.common.database.dialect;
import cn.datax.common.database.core.DbColumn;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
/**
* MySql 数据库方言
*
* @author yuwei
* @since 2020-03-14
*/
public class MySqlDialect extends AbstractDbDialect {
@Override
public RowMapper<DbColumn> rowMapper() {
return (ResultSet rs, int rowNum) -> {
DbColumn entity = new DbColumn();
entity.setName(rs.getString("Field"));
entity.setType(rs.getString("Type"));
entity.setNullable(rs.getString("Null"));
entity.setHasKey(rs.getString("Key"));
entity.setLength(rs.getString("Extra"));
return entity;
};
}
}
package cn.datax.common.database.dialect;
/**
* ORACLE Oracle12c+数据库方言
*
* @author yuwei
* @since 2020-03-14
*/
public class Oracle12cDialect extends OracleDialect {
@Override
public String buildPaginationSql(String originalSql, long offset, long count) {
StringBuilder sqlBuilder = new StringBuilder(originalSql);
sqlBuilder.append(" OFFSET ").append(offset).append(" ROWS FETCH NEXT ").append(count).append(" ROWS ONLY ");
return sqlBuilder.toString();
}
}
package cn.datax.common.database.dialect;
import cn.datax.common.database.core.DbColumn;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
/**
* Oracle Oracle11g及以下数据库方言
*
* @author yuwei
* @since 2020-03-14
*/
public class OracleDialect extends AbstractDbDialect {
@Override
public String columns(String tableName) {
return "select * from user_tab_columns where table_name = '" + tableName + "' ";
}
@Override
public String tables(String dbName) {
return "SELECT u.TABLE_NAME FROM user_tables u";
}
@Override
public String buildPaginationSql(String originalSql, long offset, long count) {
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append("SELECT * FROM ( SELECT TMP.*, ROWNUM ROW_ID FROM ( ");
sqlBuilder.append(originalSql).append(" ) TMP WHERE ROWNUM <=").append((offset >= 1) ? (offset + count) : count);
sqlBuilder.append(") WHERE ROW_ID > ").append(offset);
return sqlBuilder.toString();
}
@Override
public RowMapper<DbColumn> rowMapper() {
return (ResultSet rs, int rowNum) -> {
DbColumn entity = new DbColumn();
entity.setName(rs.getString("COLUMN_NAME"));
entity.setType(rs.getString("DATA_TYPE"));
entity.setNullable(rs.getString("NULLABLE"));
return entity;
};
}
}
package cn.datax.common.database.dialect;
import cn.datax.common.database.core.DbColumn;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
/**
* Postgre 数据库方言
*
* @author yuwei
* @since 2020-03-14
*/
public class PostgreDialect extends AbstractDbDialect {
@Override
public String columns(String tableName) {
String sql = "SELECT a.attnum,\n" +
"a.attname AS field,\n" +
"t.typname AS type,\n" +
"a.attlen AS length,\n" +
"a.atttypmod AS lengthvar,\n" +
"a.attnotnull AS notnull,\n" +
"b.description AS comment\n" +
"FROM pg_class c,\n" +
"pg_attribute a\n" +
"LEFT OUTER JOIN pg_description b ON a.attrelid=b.objoid AND a.attnum = b.objsubid,\n" +
"pg_type t\n" +
"WHERE c.relname = 'teble_a'\n" +
"and a.attnum > 0\n" +
"and a.attrelid = c.oid\n" +
"and a.atttypid = t.oid\n" +
"ORDER BY a.attnum;";
return sql;
}
@Override
public String tables(String dbName) {
return "select tablename from pg_tables WHERE schemaname = 'public' AND tableowner = '" + dbName + "'";
}
@Override
public String buildPaginationSql(String originalSql, long offset, long count) {
StringBuilder sqlBuilder = new StringBuilder(originalSql);
sqlBuilder.append(" LIMIT ").append(offset).append(" offset ").append(count);
return sqlBuilder.toString();
}
@Override
public RowMapper<DbColumn> rowMapper() {
return (ResultSet rs, int rowNum) -> {
DbColumn entity = new DbColumn();
entity.setName(rs.getString("field"));
entity.setType(rs.getString("type"));
entity.setNullable(rs.getString("notnull"));
return entity;
};
}
}
package cn.datax.common.database.dialect;
import cn.datax.common.database.core.DbColumn;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.util.StringUtils;
import java.sql.ResultSet;
/**
* SQLServer 2005 数据库方言
*
* @author yuwei
* @since 2020-03-14
*/
public class SQLServer2008Dialect extends AbstractDbDialect {
@Override
public String columns(String tableName) {
return "sp_columns " + tableName + ";";
}
@Override
public String tables(String dbName) {
return "SELECT Name FROM " + dbName + "..SysObjects Where XType='U' ";
}
private static String getOrderByPart(String sql) {
String loweredString = sql.toLowerCase();
int orderByIndex = loweredString.indexOf("order by");
if (orderByIndex != -1) {
return sql.substring(orderByIndex);
} else {
return "";
}
}
@Override
public String buildPaginationSql(String originalSql, long offset, long count) {
StringBuilder pagingBuilder = new StringBuilder();
String orderby = getOrderByPart(originalSql);
String distinctStr = "";
String loweredString = originalSql.toLowerCase();
String sqlPartString = originalSql;
if (loweredString.trim().startsWith("select")) {
int index = 6;
if (loweredString.startsWith("select distinct")) {
distinctStr = "DISTINCT ";
index = 15;
}
sqlPartString = sqlPartString.substring(index);
}
pagingBuilder.append(sqlPartString);
// if no ORDER BY is specified use fake ORDER BY field to avoid errors
if (StringUtils.isEmpty(orderby)) {
orderby = "ORDER BY CURRENT_TIMESTAMP";
}
StringBuilder sql = new StringBuilder();
sql.append("WITH selectTemp AS (SELECT ").append(distinctStr).append("TOP 100 PERCENT ")
.append(" ROW_NUMBER() OVER (").append(orderby).append(") as __row_number__, ").append(pagingBuilder)
.append(") SELECT * FROM selectTemp WHERE __row_number__ BETWEEN ")
//FIX#299:原因:mysql中limit 10(offset,size) 是从第10开始(不包含10),;而这里用的BETWEEN是两边都包含,所以改为offset+1
.append(offset + 1)
.append(" AND ")
.append(offset + count).append(" ORDER BY __row_number__");
return sql.toString();
}
@Override
public RowMapper<DbColumn> rowMapper() {
return (ResultSet rs, int rowNum) -> {
DbColumn entity = new DbColumn();
entity.setName(rs.getString("COLUMN_NAME"));
entity.setType(rs.getString("TYPE_NAME"));
entity.setNullable(rs.getString("IS_NULLABLE"));
return entity;
};
}
}
package cn.datax.common.database.dialect;
/**
* SQLServer 数据库方言
*
* @author yuwei
* @since 2020-03-14
*/
public class SQLServerDialect extends SQLServer2008Dialect {
@Override
public String buildPaginationSql(String originalSql, long offset, long count) {
StringBuilder sqlBuilder = new StringBuilder(originalSql);
sqlBuilder.append(" OFFSET ").append(offset).append(" ROWS FETCH NEXT ").append(count).append(" ROWS ONLY ");
return sqlBuilder.toString();
}
}
package cn.datax.common.database.dialect;
import cn.datax.common.database.core.DbColumn;
import cn.datax.common.database.exception.DataQueryException;
import org.springframework.jdbc.core.RowMapper;
/**
* 未知 数据库方言
*
* @author yuwei
* @since 2020-03-14
*/
public class UnknownDialect extends AbstractDbDialect {
@Override
public String columns(String tableName) {
throw new DataQueryException("不支持的数据库类型");
}
@Override
public String tables(String dbName) {
throw new DataQueryException("不支持的数据库类型");
}
@Override
public String buildPaginationSql(String sql, long offset, long count) {
throw new DataQueryException("不支持的数据库类型");
}
@Override
public String count(String sql) {
throw new DataQueryException("不支持的数据库类型");
}
@Override
public RowMapper<DbColumn> rowMapper() {
throw new DataQueryException("不支持的数据库类型");
}
}
package cn.datax.common.database.exception;
public class DataQueryException extends RuntimeException {
public DataQueryException(String message) {
super(message);
}
}
package cn.datax.common.database.query;
import cn.datax.common.database.DbDialect;
import cn.datax.common.database.DbQuery;
import cn.datax.common.database.core.DbColumn;
import cn.datax.common.database.core.PageResult;
import cn.datax.common.database.exception.DataQueryException;
import com.zaxxer.hikari.HikariDataSource;
import lombok.Setter;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
@Setter
public abstract class AbstractDbQuery implements DbQuery {
protected DataSource dataSource;
protected JdbcTemplate jdbcTemplate;
protected DbDialect dbDialect;
@Override
public boolean valid() throws SQLException {
Connection conn = dataSource.getConnection();
boolean valid = conn.isValid(0);
if (conn != null) {
conn.close();
}
return valid;
}
@Override
public void close() {
if (dataSource instanceof HikariDataSource) {
((HikariDataSource) dataSource).close();
} else {
throw new DataQueryException("不合法数据源类型");
}
}
@Override
public List<DbColumn> getTableColumns(String dbName, String tableName) {
String sql = dbDialect.columns(tableName);
return jdbcTemplate.query(sql, dbDialect.rowMapper());
}
@Override
public List<String> getTables(String dbName) {
return jdbcTemplate.queryForList(dbDialect.tables(dbName), String.class);
}
@Override
public int count(String sql) {
return jdbcTemplate.queryForObject(dbDialect.count(sql), Integer.class);
}
@Override
public List<Map<String, Object>> queryList(String sql) {
return jdbcTemplate.queryForList(sql);
}
@Override
public PageResult<Map<String, Object>> queryByPage(String sql, long offset, long size) {
int total = count(sql);
String pageSql = dbDialect.buildPaginationSql(sql, offset, size);
List<Map<String, Object>> records = jdbcTemplate.queryForList(pageSql);
return new PageResult<>(total, records);
}
}
package cn.datax.common.database.query;
public class MariaDBQuery extends AbstractDbQuery {
}
package cn.datax.common.database.query;
public class MySqlQuery extends AbstractDbQuery {
}
package cn.datax.common.database.query;
public class Oracle12cQuery extends AbstractDbQuery {
}
package cn.datax.common.database.query;
public class OracleQuery extends AbstractDbQuery {
}
package cn.datax.common.database.query;
public class PostgreQuery extends AbstractDbQuery {
}
package cn.datax.common.database.query;
import cn.datax.common.database.DbQuery;
import cn.datax.common.database.constants.DbType;
import java.util.EnumMap;
import java.util.Map;
public class QueryRegistry {
private final Map<DbType, DbQuery> query_enum_map = new EnumMap<>(DbType.class);
public QueryRegistry() {
query_enum_map.put(DbType.MARIADB, new MariaDBQuery());
query_enum_map.put(DbType.MYSQL, new MySqlQuery());
query_enum_map.put(DbType.ORACLE_12C, new Oracle12cQuery());
query_enum_map.put(DbType.ORACLE, new OracleQuery());
query_enum_map.put(DbType.POSTGRE_SQL, new PostgreQuery());
query_enum_map.put(DbType.SQL_SERVER2008, new SQLServer2008Query());
query_enum_map.put(DbType.SQL_SERVER, new SQLServerQuery());
query_enum_map.put(DbType.OTHER, new UnknownQuery());
}
public DbQuery getQuery(DbType dbType) {
return query_enum_map.get(dbType);
}
}
package cn.datax.common.database.query;
public class SQLServer2008Query extends AbstractDbQuery {
}
package cn.datax.common.database.query;
public class SQLServerQuery extends AbstractDbQuery {
}
package cn.datax.common.database.query;
public class UnknownQuery extends AbstractDbQuery {
}
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
<module>datax-common-mybatis</module> <module>datax-common-mybatis</module>
<module>datax-common-security</module> <module>datax-common-security</module>
<module>datax-common-log</module> <module>datax-common-log</module>
<module>datax-common-database</module>
</modules> </modules>
</project> </project>
\ No newline at end of file
...@@ -55,17 +55,6 @@ spring: ...@@ -55,17 +55,6 @@ spring:
args: args:
name: fileFallback name: fileFallback
fallbackUri: forward:/fallback fallbackUri: forward:/fallback
# 数据工厂中心
- id: datax-service-data-factory
uri: lb://datax-service-data-factory
predicates:
- Path=/data/factory/**
filters:
- StripPrefix=1
- name: Hystrix
args:
name: dataFactoryFallback
fallbackUri: forward:/fallback
# 即时通讯中心 # 即时通讯中心
- id: datax-websocket-server - id: datax-websocket-server
uri: ws://localhost:9876 uri: ws://localhost:9876
......
# 数据源配置
spring:
redis:
database: 1
host: 127.0.0.1
port: 6379
password: # 密码(默认为空)
timeout: 6000ms # 连接超时时长(毫秒)
lettuce:
pool:
max-active: 1000 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 10 # 连接池中的最大空闲连接
min-idle: 5 # 连接池中的最小空闲连接
datasource:
dynamic:
type: com.zaxxer.hikari.HikariDataSource
hikari:
auto-commit: false
connection-timeout: 30000
idle-timeout: 25000
login-timeout: 5
max-lifetime: 30000
read-only: false
validation-timeout: 3000
maximum-pool-size: 15
minimum-idle: 5
pool-name: DataxHikariCP
connection-test-query: SELECT 1 FROM DUAL
data-source-properties:
cachePrepStmts: true
prepStmtCacheSize: 250
prepStmtCacheSqlLimit: 2048
useServerPrepStmts: true
useLocalSessionState: true
rewriteBatchedStatements: true
cacheResultSetMetadata: true
cacheServerConfiguration: true
elideSetAutoCommits: true
maintainTimeStats: false
primary: mysql
datasource:
mysql:
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:mysql://127.0.0.1:3306/data_cloud?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 1234@abcd
mybatis-plus:
mapper-locations: classpath*:mapper/*Mapper.xml
type-aliases-package: cn.datax.service.data.factory.api.entity
global-config:
db-config:
id-type: ASSIGN_ID
banner: false
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
call-setters-on-nulls: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# spring security 配置
security:
oauth2:
client:
access-token-uri: http://localhost:8612/auth/oauth/token
user-authorization-uri: http://localhost:8612/auth/oauth/authorize
client-id: datax
client-secret: 123456
scope: all
resource:
loadBalanced: true
token-info-uri: http://localhost:8612/auth/oauth/check_token
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>datax-modules</artifactId>
<groupId>cn.datax</groupId>
<version>1.0.0</version>
</parent>
<packaging>pom</packaging>
<modelVersion>4.0.0</modelVersion>
<artifactId>data-assets-service-parent</artifactId>
<description>数据资产</description>
<modules></modules>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>data-factory-service-parent</artifactId>
<groupId>cn.datax</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>data-factory-service-api</artifactId>
<dependencies>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger2.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
<version>${swagger2.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger2.version}</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>${swagger-bootstrap.version}</version>
</dependency>
<!--feign 依赖-->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>cn.datax</groupId>
<artifactId>datax-common-core</artifactId>
<version>${app.version}</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package cn.datax.service.data.factory.api.dto;
import cn.datax.common.validate.ValidationGroups;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* <p>
* 数据源信息表 实体DTO
* </p>
*
* @author yuwei
* @since 2020-03-14
*/
@ApiModel(value = "数据源信息表Model")
@Data
public class DataSourceDto implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "主键ID")
@NotBlank(message = "主键ID不能为空", groups = {ValidationGroups.Update.class})
private String id;
@ApiModelProperty(value = "数据源类型")
@NotBlank(message = "数据源类型不能为空", groups = {ValidationGroups.Insert.class, ValidationGroups.Update.class})
private String dbType;
@ApiModelProperty(value = "数据源名称")
@NotBlank(message = "数据源名称不能为空", groups = {ValidationGroups.Insert.class, ValidationGroups.Update.class})
private String sourceName;
@ApiModelProperty(value = "数据源描述")
@NotBlank(message = "数据源描述不能为空", groups = {ValidationGroups.Insert.class, ValidationGroups.Update.class})
private String sourceDesc;
@ApiModelProperty(value = "数据源连接信息")
@Valid
private DbSchemaDto dbSchema;
}
package cn.datax.service.data.factory.api.dto;
import cn.datax.common.validate.ValidationGroups;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
@ApiModel(value = "数据源连接信息Model")
@Data
public class DbSchemaDto implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "主机")
@NotBlank(message = "主机不能为空", groups = {ValidationGroups.Insert.class, ValidationGroups.Update.class})
private String host;
@ApiModelProperty(value = "端口")
@NotNull(message = "端口不能为空", groups = {ValidationGroups.Insert.class, ValidationGroups.Update.class})
private Integer port;
@ApiModelProperty(value = "数据库")
@NotBlank(message = "数据库不能为空", groups = {ValidationGroups.Insert.class, ValidationGroups.Update.class})
private String dbName;
@ApiModelProperty(value = "用户名")
@NotBlank(message = "用户名不能为空", groups = {ValidationGroups.Insert.class, ValidationGroups.Update.class})
private String username;
@ApiModelProperty(value = "密码")
@NotBlank(message = "密码不能为空", groups = {ValidationGroups.Insert.class, ValidationGroups.Update.class})
private String password;
}
package cn.datax.service.data.factory.api.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import cn.datax.common.base.BaseEntity;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* <p>
* 数据源信息表
* </p>
*
* @author yuwei
* @since 2020-03-14
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName(value = "data_source", autoResultMap = true)
public class DataSourceEntity extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 数据源类型
*/
private String dbType;
/**
* 数据源名称
*/
private String sourceName;
/**
* 数据源描述
*/
private String sourceDesc;
/**
* 数据源连接信息
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private DbSchema dbSchema;
}
package cn.datax.service.data.factory.api.entity;
import lombok.Data;
import java.io.Serializable;
@Data
public class DbSchema implements Serializable {
private static final long serialVersionUID = 1L;
private String host;
private String username;
private String password;
private Integer port;
private String dbName;
}
package cn.datax.service.data.factory.api.query;
import cn.datax.common.base.BaseQueryParams;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 数据源信息表 查询实体
* </p>
*
* @author yuwei
* @since 2020-03-14
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class DataSourceQuery extends BaseQueryParams {
private static final long serialVersionUID=1L;
private String sourceName;
}
package cn.datax.service.data.factory.api.query;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* <p>
* 数据查询 查询实体
* </p>
*
* @author yuwei
* @since 2020-03-14
*/
@Data
public class DbDataQuery implements Serializable {
private static final long serialVersionUID = 1L;
@NotBlank(message = "数据源不能为空")
private String dataSourceId;
@NotBlank(message = "查询sql不能为空")
private String sql;
// 当前页码
private Integer pageNum = 1;
// 分页条数
private Integer pageSize = 20;
public Integer getOffset() {
pageSize = pageSize == null ? 20 : pageSize;
pageNum = pageNum == null ? 1 : pageNum;
int offset = pageNum > 0 ? (pageNum - 1) * pageSize : 0;
return offset;
}
}
package cn.datax.service.data.factory.api.vo;
import cn.datax.service.data.factory.api.entity.DbSchema;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 数据源信息表 实体VO
* </p>
*
* @author yuwei
* @since 2020-03-14
*/
@Data
public class DataSourceVo implements Serializable {
private static final long serialVersionUID=1L;
private String id;
private Integer status;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime createTime;
private String dbType;
private String sourceName;
private String sourceDesc;
private DbSchema dbSchema;
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>data-factory-service-parent</artifactId>
<groupId>cn.datax</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>data-factory-service</artifactId>
<dependencies>
<!--web 模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!--配置中心客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cn.datax</groupId>
<artifactId>datax-common-mybatis</artifactId>
<version>${app.version}</version>
</dependency>
<dependency>
<groupId>cn.datax</groupId>
<artifactId>datax-common-redis</artifactId>
<version>${app.version}</version>
</dependency>
<dependency>
<groupId>cn.datax</groupId>
<artifactId>datax-common-security</artifactId>
<version>${app.version}</version>
</dependency>
<dependency>
<groupId>cn.datax</groupId>
<artifactId>datax-common-database</artifactId>
<version>${app.version}</version>
</dependency>
<dependency>
<groupId>cn.datax</groupId>
<artifactId>datax-common-log</artifactId>
<version>${app.version}</version>
</dependency>
<dependency>
<groupId>cn.datax</groupId>
<artifactId>data-factory-service-api</artifactId>
<version>${app.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package cn.datax.service.data.factory;
import cn.datax.common.database.annotation.EnableDatabase;
import cn.datax.common.log.annotation.EnableDataLog;
import cn.datax.common.mybatis.annotation.EnableDataMybatis;
import cn.datax.common.redis.annotation.EnableDataRedis;
import cn.datax.common.security.annotation.EnableDataFeignClients;
import cn.datax.common.security.annotation.EnableDataSecurity;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
@EnableDataSecurity
@EnableDataMybatis
@EnableDataRedis
@EnableDataLog
@EnableDataFeignClients
@EnableDatabase
@SpringCloudApplication
public class DataFactoryApplication {
public static void main(String[] args) {
SpringApplication.run(DataFactoryApplication.class);
}
}
package cn.datax.service.data.factory.config;
import cn.datax.common.security.handler.DataAccessDeniedHandler;
import cn.datax.common.security.handler.DataAuthExceptionEntryPoint;
import cn.datax.common.security.utils.DataRedisTokenServices;
import cn.datax.common.security.utils.RedisTokenStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class DataResourceServerConfig extends ResourceServerConfigurerAdapter {
@Autowired
private DataAccessDeniedHandler accessDeniedHandler;
@Autowired
private DataAuthExceptionEntryPoint exceptionEntryPoint;
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
public TokenStore redisTokenStore() {
return new RedisTokenStore(redisConnectionFactory);
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
DataRedisTokenServices dataTokenServices = new DataRedisTokenServices();
dataTokenServices.setTokenStore(redisTokenStore());
resources
.tokenStore(redisTokenStore())
.tokenServices(dataTokenServices)
.authenticationEntryPoint(exceptionEntryPoint)
.accessDeniedHandler(accessDeniedHandler);
}
@Override
public void configure(HttpSecurity http) throws Exception {
//允许使用iframe 嵌套,避免swagger-ui 不被加载的问题
http.headers().frameOptions().disable();
http.authorizeRequests()
.antMatchers(
"/actuator/**",
"/v2/api-docs/**",
"/swagger-ui.html",
"/doc.html",
"/swagger-resources/**",
"/webjars/**",
// feign 内部调用不用授权
"/inner/**"
).permitAll()
.anyRequest().authenticated()
.and().csrf().disable();
}
}
package cn.datax.service.data.factory.config;
import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMethod;
import springfox.documentation.builders.*;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.Parameter;
import springfox.documentation.service.ResponseMessage;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableSwagger2
@EnableSwaggerBootstrapUI
public class SwaggerConfig {
/**
* 创建API应用
* apiInfo() 增加API相关信息
* 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现,
* 本例采用指定扫描的包路径来定义指定要建立API的目录。
*
* @return
*/
@Bean
public Docket createRestApi(){
//版本类型是swagger2
return new Docket(DocumentationType.SWAGGER_2)
//通过调用自定义方法apiInfo,获得文档的主要信息
.apiInfo(apiInfo())
//设置全局参数
.globalOperationParameters(globalParamBuilder())
//设置全局响应参数
.globalResponseMessage(RequestMethod.GET,responseBuilder())
.globalResponseMessage(RequestMethod.POST,responseBuilder())
.globalResponseMessage(RequestMethod.PUT,responseBuilder())
.globalResponseMessage(RequestMethod.DELETE,responseBuilder())
.select()
.apis(RequestHandlerSelectors.basePackage("cn.datax.service.data.factory.controller"))//扫描该包下面的API注解
.paths(PathSelectors.any())
.build()
//设置安全认证
.securitySchemes(security());
}
/**
* 创建该API的基本信息(这些基本信息会展现在文档页面中)
* 访问地址:http://项目实际地址/swagger-ui.html
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("数据工厂管理中心") //接口管理文档首页显示
.description("数据工厂管理中心接口文档") //API的描述
.version("1.0")
.build();
}
/**
* 安全认证参数
* @return
*/
private List<ApiKey> security() {
List<ApiKey> apiKeys = new ArrayList<>();
apiKeys.add(new ApiKey("Authorization", "Authorization", "header"));
return apiKeys;
}
/**
* 构建全局参数列表
* @return
*/
private List<Parameter> globalParamBuilder(){
List<Parameter> pars = new ArrayList<>();
pars.add(parameterBuilder("Authorization","令牌","string","header",false).build());
return pars;
}
/**
* 创建参数
* @return
*/
private ParameterBuilder parameterBuilder(String name, String desc, String type, String parameterType, boolean required) {
ParameterBuilder tokenPar = new ParameterBuilder();
tokenPar.name(name).description(desc).modelRef(new ModelRef(type)).parameterType(parameterType).required(required).build();
return tokenPar;
}
/**
* 创建全局响应值
* @return
*/
private List<ResponseMessage> responseBuilder() {
List<ResponseMessage> responseMessageList = new ArrayList<>();
responseMessageList.add(new ResponseMessageBuilder().code(200).message("响应成功").build());
responseMessageList.add(new ResponseMessageBuilder().code(500).message("服务器内部错误").build());
return responseMessageList;
}
}
package cn.datax.service.data.factory.controller;
import cn.datax.common.core.JsonPage;
import cn.datax.common.core.R;
import cn.datax.common.database.DbQuery;
import cn.datax.common.database.core.DbColumn;
import cn.datax.common.database.core.PageResult;
import cn.datax.common.validate.ValidationGroups;
import cn.datax.service.data.factory.api.dto.DataSourceDto;
import cn.datax.service.data.factory.api.entity.DataSourceEntity;
import cn.datax.service.data.factory.api.query.DataSourceQuery;
import cn.datax.service.data.factory.api.query.DbDataQuery;
import cn.datax.service.data.factory.api.vo.DataSourceVo;
import cn.datax.service.data.factory.mapstruct.DataSourceMapper;
import cn.datax.service.data.factory.service.DataSourceService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import cn.datax.common.base.BaseController;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* <p>
* 数据源信息表 前端控制器
* </p>
*
* @author yuwei
* @since 2020-03-14
*/
@Api(tags = {"数据源信息表"})
@RestController
@RequestMapping("/dataSource")
public class DataSourceController extends BaseController {
@Autowired
private DataSourceService dataSourceService;
@Autowired
private DataSourceMapper dataSourceMapper;
/**
* 通过ID查询信息
*
* @param id
* @return
*/
@ApiOperation(value = "获取详细信息", notes = "根据url的id来获取详细信息")
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
@GetMapping("/{id}")
public R getDataSourceById(@PathVariable String id) {
DataSourceEntity dataSourceEntity = dataSourceService.getById(id);
return R.ok().setData(dataSourceMapper.toVO(dataSourceEntity));
}
/**
* 分页查询信息
*
* @param dataSourceQuery
* @return
*/
@ApiOperation(value = "分页查询", notes = "")
@ApiImplicitParams({
@ApiImplicitParam(name = "dataSourceQuery", value = "查询实体dataSourceQuery", required = true, dataTypeClass = DataSourceQuery.class)
})
@GetMapping("/page")
public R getRolePage(DataSourceQuery dataSourceQuery) {
QueryWrapper<DataSourceEntity> queryWrapper = new QueryWrapper<>();
IPage<DataSourceEntity> page = dataSourceService.page(new Page<>(dataSourceQuery.getPageNum(), dataSourceQuery.getPageSize()), queryWrapper);
List<DataSourceVo> collect = page.getRecords().stream().map(dataSourceMapper::toVO).collect(Collectors.toList());
JsonPage<DataSourceVo> jsonPage = new JsonPage<>(page.getCurrent(), page.getSize(), page.getTotal(), collect);
return R.ok().setData(jsonPage);
}
/**
* 添加
* @param dataSource
* @return
*/
@ApiOperation(value = "添加信息", notes = "根据dataSource对象添加信息")
@ApiImplicitParam(name = "dataSource", value = "详细实体dataSource", required = true, dataType = "DataSourceDto")
@PostMapping()
public R saveDataSource(@RequestBody @Validated({ValidationGroups.Insert.class}) DataSourceDto dataSource) {
dataSourceService.saveDataSource(dataSource);
return R.ok();
}
/**
* 修改
* @param dataSource
* @return
*/
@ApiOperation(value = "修改信息", notes = "根据url的id来指定修改对象,并根据传过来的信息来修改详细信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path"),
@ApiImplicitParam(name = "dataSource", value = "详细实体dataSource", required = true, dataType = "DataSourceDto")
})
@PutMapping("/{id}")
public R updateDataSource(@PathVariable String id, @RequestBody @Validated({ValidationGroups.Update.class}) DataSourceDto dataSource) {
dataSourceService.updateDataSource(dataSource);
return R.ok();
}
/**
* 删除
* @param id
* @return
*/
@ApiOperation(value = "删除", notes = "根据url的id来指定删除对象")
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path")
@DeleteMapping("/{id}")
public R deleteDataSourceById(@PathVariable String id) {
dataSourceService.deleteDataSourceById(id);
return R.ok();
}
/**
* 数据库类型
* @return
*/
@ApiOperation(value = "数据库类型", notes = "获取数据库类型")
@GetMapping("/dbTypes")
public R getDbTypes() {
List<Map<String, Object>> dbTypes = dataSourceService.getDbTypes();
return R.ok().setData(dbTypes);
}
/**
* 检测数据库连通性
* @param dataSource
* @return
*/
@ApiOperation(value = "数据库连通性", notes = "根据数据库配置信息检测数据库连通性")
@ApiImplicitParam(name = "dataSource", value = "详细实体dataSource", required = true, dataType = "DataSourceDto")
@PostMapping("/checkConnection")
public R checkConnection(@RequestBody @Validated({ValidationGroups.Insert.class}) DataSourceDto dataSource) {
DbQuery dbQuery = dataSourceService.checkConnection(dataSource);
boolean valid = false;
try {
valid = dbQuery.valid();
} catch (SQLException e) {
e.printStackTrace();
return R.error(e.getMessage());
}
return valid ? R.ok() : R.error("数据库连接有误,请检查数据库配置是否正确");
}
/**
* 数据库表
* @param id
* @return
*/
@ApiOperation(value = "数据库表", notes = "根据数据源的id来获取指定数据库表")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path"),
@ApiImplicitParam(name = "dbName", value = "数据库表名", required = true, dataType = "String", paramType = "path")
})
@GetMapping("/{id}/{dbName}/tables")
public R getDbTables(@PathVariable String id, @PathVariable String dbName) {
DbQuery dbQuery = dataSourceService.getDbTables(id);
List<String> tables = dbQuery.getTables(dbName);
return R.ok().setData(tables);
}
/**
* 数据库表结构
* @param id
* @return
*/
@ApiOperation(value = "数据库表结构", notes = "根据数据源的id来获取指定数据库表的表结构")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "String", paramType = "path"),
@ApiImplicitParam(name = "dbName", value = "数据库名", required = true, dataType = "String", paramType = "path"),
@ApiImplicitParam(name = "tableName", value = "数据表名", required = true, dataType = "String", paramType = "path")
})
@GetMapping("/{id}/{dbName}/{tableName}/columns")
public R getDbTableColumns(@PathVariable String id, @PathVariable String dbName, @PathVariable String tableName) {
DbQuery dbQuery = dataSourceService.getDbTables(id);
List<DbColumn> columns = dbQuery.getTableColumns(dbName, tableName);
return R.ok().setData(columns);
}
@ApiOperation(value = "获取SQL结果", notes = "根据数据源的id来获取SQL结果")
@ApiImplicitParam(name = "dbDataQuery", value = "详细实体dbDataQuery", required = true, dataType = "DbDataQuery")
@GetMapping("/queryList")
public R queryList(@RequestBody @Validated DbDataQuery dbDataQuery) {
DbQuery dbQuery = dataSourceService.getDbTables(dbDataQuery.getDataSourceId());
List<Map<String, Object>> list = dbQuery.queryList(dbDataQuery.getSql());
return R.ok().setData(list);
}
@ApiOperation(value = "分页获取SQL结果", notes = "根据数据源的id来分页获取SQL结果")
@ApiImplicitParam(name = "dbDataQuery", value = "详细实体dbDataQuery", required = true, dataType = "DbDataQuery")
@GetMapping("/queryByPage")
public R queryByPage(@RequestBody @Validated DbDataQuery dbDataQuery) {
DbQuery dbQuery = dataSourceService.getDbTables(dbDataQuery.getDataSourceId());
PageResult<Map<String, Object>> page = dbQuery.queryByPage(dbDataQuery.getSql(), dbDataQuery.getOffset(), dbDataQuery.getPageSize());
page.setPageNum(dbDataQuery.getPageNum()).setPageSize(dbDataQuery.getPageSize());
return R.ok().setData(page);
}
}
package cn.datax.service.data.factory.dao;
import cn.datax.common.base.BaseDao;
import cn.datax.service.data.factory.api.entity.DataSourceEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 数据源信息表 Mapper 接口
* </p>
*
* @author yuwei
* @since 2020-03-14
*/
@Mapper
public interface DataSourceDao extends BaseDao<DataSourceEntity> {
}
package cn.datax.service.data.factory.mapstruct;
import cn.datax.common.mapstruct.EntityMapper;
import cn.datax.service.data.factory.api.dto.DataSourceDto;
import cn.datax.service.data.factory.api.entity.DataSourceEntity;
import cn.datax.service.data.factory.api.vo.DataSourceVo;
import org.mapstruct.Mapper;
/**
* <p>
* 数据源信息表 Mapper 实体映射
* </p>
*
* @author yuwei
* @since 2020-03-14
*/
@Mapper(componentModel = "spring")
public interface DataSourceMapper extends EntityMapper<DataSourceDto, DataSourceEntity, DataSourceVo> {
}
package cn.datax.service.data.factory.service;
import cn.datax.common.database.DbQuery;
import cn.datax.service.data.factory.api.dto.DataSourceDto;
import cn.datax.service.data.factory.api.entity.DataSourceEntity;
import cn.datax.common.base.BaseService;
import java.util.List;
import java.util.Map;
/**
* <p>
* 数据源信息表 服务类
* </p>
*
* @author yuwei
* @since 2020-03-14
*/
public interface DataSourceService extends BaseService<DataSourceEntity> {
void saveDataSource(DataSourceDto dataSource);
void updateDataSource(DataSourceDto dataSource);
void deleteDataSourceById(String id);
DbQuery checkConnection(DataSourceDto dataSource);
List<Map<String, Object>> getDbTypes();
DbQuery getDbTables(String id);
}
package cn.datax.service.data.factory.service.impl;
import cn.datax.common.database.DataSourceFactory;
import cn.datax.common.database.DbQuery;
import cn.datax.common.database.constants.DbQueryProperty;
import cn.datax.common.database.constants.DbType;
import cn.datax.service.data.factory.api.dto.DataSourceDto;
import cn.datax.service.data.factory.api.entity.DbSchema;
import cn.datax.service.data.factory.api.entity.DataSourceEntity;
import cn.datax.service.data.factory.dao.DataSourceDao;
import cn.datax.service.data.factory.service.DataSourceService;
import cn.datax.service.data.factory.mapstruct.DataSourceMapper;
import cn.datax.common.base.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* <p>
* 数据源信息表 服务实现类
* </p>
*
* @author yuwei
* @since 2020-03-14
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class DataSourceServiceImpl extends BaseServiceImpl<DataSourceDao, DataSourceEntity> implements DataSourceService {
@Autowired
private DataSourceDao dataSourceDao;
@Autowired
private DataSourceMapper dataSourceMapper;
@Autowired
private DataSourceFactory dataSourceFactory;
@Override
@Transactional(rollbackFor = Exception.class)
public void saveDataSource(DataSourceDto dataSourceDto) {
DataSourceEntity dataSource = dataSourceMapper.toEntity(dataSourceDto);
dataSourceDao.insert(dataSource);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateDataSource(DataSourceDto dataSourceDto) {
DataSourceEntity dataSource = dataSourceMapper.toEntity(dataSourceDto);
dataSourceDao.updateById(dataSource);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteDataSourceById(String id) {
dataSourceDao.deleteById(id);
}
@Override
public DbQuery checkConnection(DataSourceDto dataSourceDto) {
DataSourceEntity dataSource = dataSourceMapper.toEntity(dataSourceDto);
DbSchema dbSchema = dataSource.getDbSchema();
DbQueryProperty dbQueryProperty = new DbQueryProperty(dataSource.getDbType(), dbSchema.getHost(),
dbSchema.getUsername(), dbSchema.getPassword(), dbSchema.getPort(), dbSchema.getDbName());
DbQuery dbQuery = dataSourceFactory.createDbQuery(dbQueryProperty);
return dbQuery;
}
@Override
public List<Map<String, Object>> getDbTypes() {
return Arrays.stream(DbType.values()).map(s -> {
Map<String, Object> map = new HashMap<>();
map.put("type", s.getDb());
map.put("name", s.getDesc());
return map;
}).collect(Collectors.toList());
}
@Override
public DbQuery getDbTables(String id) {
DataSourceEntity dataSource = getById(id);
DbSchema dbSchema = dataSource.getDbSchema();
DbQueryProperty dbQueryProperty = new DbQueryProperty(dataSource.getDbType(), dbSchema.getHost(),
dbSchema.getUsername(), dbSchema.getPassword(), dbSchema.getPort(), dbSchema.getDbName());
DbQuery dbQuery = dataSourceFactory.createDbQuery(dbQueryProperty);
return dbQuery;
}
}
server:
port: 8813
spring:
application:
name: datax-service-data-factory
profiles:
active: dev
cloud:
config:
fail-fast: true
name: ${spring.application.name}
profile: ${spring.profiles.active}
discovery:
enabled: true
service-id: datax-config
# 注册中心配置
eureka:
instance:
lease-renewal-interval-in-seconds: 20
client:
register-with-eureka: true
fetch-registry: true
instance-info-replication-interval-seconds: 30
registry-fetch-interval-seconds: 3
service-url:
defaultZone: http://localhost:8610/eureka
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.datax.service.data.factory.dao.DataSourceDao">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="cn.datax.service.data.factory.api.entity.DataSourceEntity">
<result column="id" property="id" />
<result column="status" property="status" />
<result column="create_by" property="createBy" />
<result column="create_time" property="createTime" />
<result column="update_by" property="updateBy" />
<result column="update_time" property="updateTime" />
<result column="db_type" property="dbType" />
<result column="source_name" property="sourceName" />
<result column="source_desc" property="sourceDesc" />
<result column="db_schema" property="dbSchema" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id,
status,
create_by,
create_time,
update_by,
update_time,
db_type, source_name, source_desc, db_schema
</sql>
</mapper>
module.log=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,batch,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2
# 开启过滤
filter=true
# 配置不打印的内容
exclude=select 1
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>datax-modules</artifactId>
<groupId>cn.datax</groupId>
<version>1.0.0</version>
</parent>
<packaging>pom</packaging>
<modelVersion>4.0.0</modelVersion>
<artifactId>data-factory-service-parent</artifactId>
<description>数据工厂</description>
<modules>
<module>data-factory-service</module>
<module>data-factory-service-api</module>
</modules>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>datax-modules</artifactId>
<groupId>cn.datax</groupId>
<version>1.0.0</version>
</parent>
<packaging>pom</packaging>
<modelVersion>4.0.0</modelVersion>
<artifactId>data-master-parent</artifactId>
<description>主数据管理</description>
<modules></modules>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>datax-modules</artifactId>
<groupId>cn.datax</groupId>
<version>1.0.0</version>
</parent>
<packaging>pom</packaging>
<modelVersion>4.0.0</modelVersion>
<artifactId>data-meta-parent</artifactId>
<description>元数据管理</description>
<modules></modules>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>datax-modules</artifactId>
<groupId>cn.datax</groupId>
<version>1.0.0</version>
</parent>
<packaging>pom</packaging>
<modelVersion>4.0.0</modelVersion>
<artifactId>data-share-parent</artifactId>
<description>数据共享</description>
<modules></modules>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>datax-modules</artifactId>
<groupId>cn.datax</groupId>
<version>1.0.0</version>
</parent>
<packaging>pom</packaging>
<modelVersion>4.0.0</modelVersion>
<artifactId>data-vaild-parent</artifactId>
<description>数据质量</description>
<modules></modules>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>datax-modules</artifactId>
<groupId>cn.datax</groupId>
<version>1.0.0</version>
</parent>
<packaging>pom</packaging>
<modelVersion>4.0.0</modelVersion>
<artifactId>data-visual-parent</artifactId>
<description>数据可视化</description>
<modules></modules>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>datax-modules</artifactId>
<groupId>cn.datax</groupId>
<version>1.0.0</version>
</parent>
<packaging>pom</packaging>
<modelVersion>4.0.0</modelVersion>
<artifactId>form-making-parent</artifactId>
<description>智能表单</description>
<modules></modules>
</project>
\ No newline at end of file
...@@ -16,13 +16,5 @@ ...@@ -16,13 +16,5 @@
<module>system-service-parent</module> <module>system-service-parent</module>
<module>file-service-parent</module> <module>file-service-parent</module>
<module>email-service-parent</module> <module>email-service-parent</module>
<module>data-factory-service-parent</module>
<module>data-assets-service-parent</module>
<module>data-vaild-service-parent</module>
<module>data-share-service-parent</module>
<module>data-visual-service-parent</module>
<module>data-meta-service-parent</module>
<module>data-master-service-parent</module>
<module>form-making-service-parent</module>
</modules> </modules>
</project> </project>
\ No newline at end of file
...@@ -42,11 +42,6 @@ ...@@ -42,11 +42,6 @@
<aliyun-sdk-oss.version>3.6.0</aliyun-sdk-oss.version> <aliyun-sdk-oss.version>3.6.0</aliyun-sdk-oss.version>
<qiniu-java-sdk.version>7.2.25</qiniu-java-sdk.version> <qiniu-java-sdk.version>7.2.25</qiniu-java-sdk.version>
<fastdfs-client.version>1.26.7</fastdfs-client.version> <fastdfs-client.version>1.26.7</fastdfs-client.version>
<mysql.version>8.0.19</mysql.version>
<mariadb.version>2.5.4</mariadb.version>
<oracle.version>19.3.0.0</oracle.version>
<postgresql.version>42.2.11</postgresql.version>
<sqlserver.version>8.2.1.jre8</sqlserver.version>
</properties> </properties>
<modules> <modules>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment