This commit is contained in:
2019-04-15 17:36:06 +08:00
parent fe3ea393ba
commit 9a7953aa47
23 changed files with 325 additions and 536 deletions

View File

@@ -87,6 +87,9 @@ public final class FileKit {
return "";
}
public static String rootPath(){
return rootPath(FileKit.class);
}
/**
* 读取流内的所有内容

View File

@@ -11,6 +11,8 @@ public class JBean {
private Object body;
private long timestamp;
public final static JBean OK = by(0, "操作成功");
public static JBean by(int code, String message){
JBean jBean = new JBean();
jBean.code = code;

View File

@@ -5,7 +5,6 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

View File

@@ -0,0 +1,125 @@
package net.tccn.base;
import com.jfinal.plugin.activerecord.SqlPara;
import com.jfinal.plugin.activerecord.sql.SqlKit;
import java.io.File;
import java.io.FileFilter;
import java.util.Map;
/**
* Created by liangxianyou at 2018/7/11 11:05.
*/
public class TplKit {
private static TplKit tplKit = null;
private static SqlKit kit = null;
private static boolean hadParse = false;// 标记 是否已经解析
private static String clazzRoot = new File(FileKit.rootPath()).getPath();
public static TplKit use() {
return use(false);
}
/**
* 获取单列的实例对象,
*
* @param isDev
* 是否开发模式, 多次调用只有第一次的 isDev生效
* @return
*/
public static TplKit use(boolean isDev) {
synchronized (TplKit.class) {
if (tplKit == null) {
tplKit = new TplKit(isDev);
}
}
return tplKit;
}
private TplKit(boolean isDev) {
kit = new SqlKit("tplKit", isDev);
}
/**
* [添加文件 到模板解析器]
*
* @param tplPath
* 文件路劲
*/
public void addTpl(String tplPath) {
kit.addSqlTemplate(tplPath);
hadParse = false;
System.out.println("addTpl" + tplPath);
}
/**
* 添加文件/目录 到模板解析器
*
* @param tplFile
* 文件/目录必须放到 resources/下面
*/
public void addTpl(File tplFile) {
addTpl(tplFile, null);
hadParse = false;
}
/**
* 添加文件/目录 到模板解析器
*
* @param tplFile
* 文件/目录
* @param filter
* 文件过滤器
*/
public void addTpl(File tplFile, FileFilter filter) {
if (tplFile.isFile()) {
addTpl(tplFile.getPath().replace(clazzRoot, "")); //以classes路径开始的路径
} else if (tplFile.isDirectory()) {
File[] files = tplFile.listFiles(filter);
for (int i = 0; i < files.length; i++) {
addTpl(files[i], filter);
}
}
hadParse = false;
}
/**
* 获取模板
*
* @param key
* 模板id
* @return
*/
public String getTpl(String key) {
if (!hadParse)
parseTpl();
return kit.getSql(key);
}
/**
* 获取模板
*
* @param key
* 模板id
* @param data
* 模板渲染数据
* @return
*/
public String getTpl(String key, Map data) {
if (!hadParse)
parseTpl();
SqlPara sqlPara = kit.getSqlPara(key, data);
return sqlPara.getSql().replaceAll("[\\s]+", " ");
}
public String getTpl(String key, Object m) {
if (!hadParse)
parseTpl();
SqlPara sqlPara = kit.getSqlPara(key, m);
return sqlPara.getSql();
}
public void parseTpl() {
kit.parseSqlTemplate();
}
}

View File

@@ -1,81 +0,0 @@
package net.tccn.dbq.jdbc;
import java.sql.Connection;
/**
* @author: liangxianyou at 2018/10/11 17:47.
*/
public class JdbcAccount {
private String url;
private String user;
private String pwd;
private String cate;//数据库类型
private Integer connectMax = 5;//默认最大连接数5
/*public JdbcAccount() {
}*/
public JdbcAccount(String url, String user, String pwd) {
this.url = url;
this.user = user;
this.pwd = pwd;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getCate() {
return cate;
}
public void setCate(String cate) {
this.cate = cate;
}
public Integer getConnectMax() {
return connectMax;
}
public void setConnectMax(Integer connectMax) {
this.connectMax = connectMax;
}
//-------------------------------------------------------
public String parse() {
int start = url.indexOf("//") + 2;
int end = url.indexOf("/", start);
int endDef = url.indexOf("?", end);
if (endDef == -1) {
endDef = url.length();
}
String host = url.substring(start, end == -1 ? url.length() : end);
return user + "@" + host;
}
public Connection getConnection() {
return null;
}
}

View File

@@ -1,154 +0,0 @@
package net.tccn.dbq.jdbc;
import net.tccn.dbq.table.Table;
import org.redkale.util.Comment;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
/**
* JdbcService.
*
* @author: liangxianyou at 2018/10/8 10:39.
*/
public class JdbcService {
private JdbcAccount account;
private static ConcurrentHashMap<JdbcAccount, Connection> jdbcPool = new ConcurrentHashMap<>();
public JdbcService(JdbcAccount account) {
this.account = account;
}
//-------------- query -----------------
private <R> List<R> executeQuery(String sql, Map columns, BiFunction<ResultSet, Map, R> fun) throws SQLException {
try (
Connection connection = DriverManager.getConnection(account.getUrl(), account.getUser(), account.getPwd());
PreparedStatement ps = connection.prepareStatement(sql);
ResultSet resultSet = ps.executeQuery()) {
List list = new ArrayList();
while (resultSet.next()) {
list.add(fun.apply(resultSet, columns));
}
return list;
}
}
public static List<String> getCatalogs(Connection connection) throws SQLException {
List<String> catalogs = new ArrayList<>();
try (
PreparedStatement ps = connection.prepareStatement("show databases;");
ResultSet rs = ps.executeQuery()
) {
while (rs.next()) {
catalogs.add(rs.getString(1));
}
}
return catalogs;
}
public static Connection getConnection(JdbcAccount account) throws SQLException {
Connection connection = jdbcPool.get(account);
if (connection == null) {
connection = DriverManager.getConnection(account.getUrl(), account.getUser(), account.getPwd());
jdbcPool.put(account, connection);
}
int i = 8000 * 12;//96000;
return connection;
}
@Comment("列表数据查询")
public static List<Map> findList(Connection connection, String sql) throws SQLException {
try (
PreparedStatement ps = connection.prepareStatement(sql);
ResultSet rs = ps.executeQuery()) {
List list = new ArrayList();
while (rs.next()) {
ResultSetMetaData metaData = rs.getMetaData();
int count = metaData.getColumnCount();
Map row = new HashMap();
for (int i = 1; i <= count; i++) {
String columnTypeName = metaData.getColumnTypeName(i);
String columnName = metaData.getColumnName(i);
row.put(columnName, null);
if (rs.getObject(i) != null) {
switch (columnTypeName) {
case "DATETIME":
case "TIMESTAMP":
case "DATE":
row.put(columnName, rs.getTimestamp(i).getTime()); break;
default:
row.put(columnName, rs.getObject(i));
}
}
}
list.add(row);
}
return list;
}
}
@Comment("统计总数")
public static int findNumber(Connection connection, String sql) throws SQLException {
try (
PreparedStatement ps = connection.prepareStatement(sql);
ResultSet rs = ps.executeQuery()) {
rs.next();
return rs.getInt(1);
}
}
public static int update(Connection connection, String sql) throws SQLException {
try (
PreparedStatement ps = connection.prepareStatement(sql);
){
return ps.executeUpdate();
}
}
// ---------------- DDL ---------------------
public static boolean createTable(Connection connection, Table table) throws SQLException {
if (table.getCatalog() != null && table.getCatalog().length() > 0) {
connection.setCatalog(table.getCatalog());
}
String tableDdl = ""; // table.getTableDdl();
System.out.println(tableDdl);
try (PreparedStatement ps = connection.prepareStatement(tableDdl)) {
return ps.execute();
}
}
public static void main(String[] args) throws SQLException {
String url = "jdbc:mysql://192.168.202.11:3306/gxbii_dev";
String user = "root";
String pwd = "eversec123098";
JdbcAccount account = new JdbcAccount(url, user, pwd);
Connection connection = account.getConnection();
System.out.println(connection);
String sql = "select * from basic_concat limit 10";
List<Map> list = JdbcService.findList(connection, sql);
System.out.println(list);
}
}

View File

@@ -1,196 +0,0 @@
package net.tccn.dbq.jdbc;
import java.sql.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
/**
* Created by liangxianyou at 2018/12/21 17:42.
*/
public class JdbcSource {
private JdbcAccount account;
private static ConcurrentHashMap<String, JdbcSource> sources = new ConcurrentHashMap<>();
private List<Connection> connections = new ArrayList<>();
private AtomicInteger connectNum = new AtomicInteger();
private JdbcSource() {
}
public JdbcSource(JdbcAccount account) {
String key = account.parse();
synchronized (sources) {
JdbcSource source = sources.get(key);
if (source == null) {
source = new JdbcSource();
}
source.account = account;
do {
try {
Connection connection = DriverManager.getConnection(account.getUrl(), account.getUser(), account.getPwd());
connections.add(connection);
} catch (SQLException e) {
e.printStackTrace();
break;
}
} while (connectNum.incrementAndGet() < 2);//默认初始化连接数 2
}
}
/**
* 获取连接
* @return
*/
private Connection getConnection() {
synchronized (connections) {
//有闲置连接,直接返回
if (connections.size() > 0) {
return connections.remove(0);
}
//没有闲置连接,总连接数小于最大连接数,创建新连接
if (connectNum.get() < account.getConnectMax()) {
try {
return DriverManager.getConnection(account.getUrl(), account.getUser(), account.getPwd());
} catch (SQLException e) {
e.printStackTrace();
}
}
//已达最大连接,且没有闲置,等待
}
return null;
}
/**
* 释放连接
* @param connection
*/
private void releaseConnection(Connection connection) {
connections.add(connection);
}
/**
* 通过Account 获取连接
* 同一个连接对象同一时刻只能被一个线程所使用,
* 两种方案:
* 1、多个连接对象每次线程得到对应的连接用完返还连接
* 2、一到多个连接每次数据库操作交给执行队列执行并返回执行结果
* @param account
* @return
*/
/*public Connection getConnection(JdbcAccount account) {
String key = account.parse();
List<Connection> conns = sources.get(key);
if (conns == null) {
conns = new ArrayList<>();
}
if (conns.size() == 0) {
try {
Connection connection = DriverManager.getConnection(account.getUrl(), account.getUser(), account.getPwd());
} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}*/
private Function<ResultSet, Map> dataToMap = (rs) -> {
Map row = new HashMap();
try {
ResultSetMetaData metaData = rs.getMetaData();
int count = metaData.getColumnCount();
for (int i = 1; i <= count; i++) {
String columnTypeName = metaData.getColumnTypeName(i);
String columnName = metaData.getColumnName(i);
row.put(columnName, null);
if (rs.getObject(i) != null) {
switch (columnTypeName) {
case "DATETIME":
case "TIMESTAMP":
case "DATE":
row.put(columnName, rs.getTimestamp(i).getTime()); break;
default:
row.put(columnName, rs.getObject(i));
}
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return row;
};
private Function<ResultSet, List<Map>> dataToList = (rs) -> {
List list = new ArrayList<>();
try {
while (rs.next()) {
list.add(dataToMap.apply(rs));
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
};
/**
* 通过sql查询 数据,
* 将每次查询任务加入到查询队列
* @param sql
* @return
*/
private Queue<String> finds = new LinkedBlockingQueue<>();
public CompletableFuture<List<Map>> find(String sql) {
return CompletableFuture.supplyAsync(() -> {
List<Map> list = null;
Connection connection = getConnection();
try (
PreparedStatement ps = connection.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
) {
list = dataToList.apply(rs);
} catch (SQLException e) {
e.printStackTrace();
}
releaseConnection(connection);
return list;
});
/*
Connection connection = getConnection(null);
try (
PreparedStatement ps = connection.prepareStatement(sql);
) {
} catch (SQLException e) {
e.printStackTrace();
}
return null;
*/
}
private void find(String sql, int cate) {
}
}

View File

@@ -2,7 +2,9 @@ package net.tccn.service;
import com.arangodb.Predicate;
import com.google.gson.Gson;
import net.tccn.base.FileKit;
import net.tccn.base.MetaKit;
import net.tccn.base.TplKit;
import org.redkale.net.http.RestMapping;
import org.redkale.service.Service;
import org.redkale.source.CacheSource;
@@ -52,7 +54,13 @@ public class BaseService implements Service {
@Resource(name = "APP_HOME")
protected File APP_HOME;
@Resource(name = "property.tplPath")
private String tplPath;
public static Properties prop = new Properties();
protected static TplKit tplKit = TplKit.use(true);
private static boolean tplInit = false;
@Override
public void init(AnyValue config) {
@@ -64,6 +72,16 @@ public class BaseService implements Service {
} catch (IOException e) {
e.printStackTrace();
}
try {
if (!tplInit) {
tplInit = true;
tplKit.addTpl(new File(FileKit.rootPath(), tplPath));
}
} catch (Exception e) {
e.printStackTrace();
}
}
@RestMapping(ignore = true)

View File

@@ -2,18 +2,18 @@ package net.tccn.service;
import net.tccn.base.JBean;
import net.tccn.base.Kv;
import net.tccn.base.MetaKit;
import net.tccn.dbq.Field;
import net.tccn.dbq.jdbc.api.DbAccount;
import net.tccn.plat.SysPlat;
import net.tccn.base.MetaKit;
import net.tccn.meta.MetaLink;
import net.tccn.meta.MetaService;
import net.tccn.meta.MetaTable;
import net.tccn.plat.SysPlat;
import org.redkale.net.http.RestMapping;
import org.redkale.net.http.RestParam;
import org.redkale.net.http.RestService;
import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.logging.Level;
import java.util.stream.Collectors;
@@ -77,31 +77,21 @@ public class MetadataService extends BaseService { //arango
//----------- 元数据管理 ---------------
@RestMapping(name = "tablelist", comment = "table列表")
public JBean tableList(@RestParam(name = "platToken") String token, String catalog, String dbPlatId, String name) {
JBean jBean = JBean.by(0, "");
SysPlat sysPlat = qtaskService.getSysPlat(token);
if (sysPlat == null) {
return jBean.set(-1, "平台信息未知");
}
JBean jBean = new JBean();
List<Kv> list = MetaKit.getMetaTables()
.stream()
.filter(x -> {
return (isEmpty.test(catalog) || catalog.equals(x.getCatalog())) &&
(isEmpty.test(dbPlatId) || dbPlatId.equals(x.getDbPlatId())) &&
(isEmpty.test(name) || x.getName().contains(name));
})
.sorted(Comparator.comparing(MetaTable::getName))
.map(x -> {
//组装返回的数据
Kv kv = Kv.of("name", x.getName())
.set("comment", x.getComment())
.set("catalog", x.getCatalog());
MetaKit.getDbPlats().stream().filter(d -> d.getKey().equals(x.getDbPlatId())).findAny().ifPresent(d -> kv.set("dbPlatName", d.getName()));
return kv;
})
.collect(Collectors.toList());
return jBean.setBody(list);
List<Kv> list =
MetaKit.getMetaTables().stream().filter(x ->
(isEmpty.test(catalog) || catalog.equals(x.getCatalog())) &&
(isEmpty.test(dbPlatId) || dbPlatId.equals(x.getDbPlatId())) &&
(isEmpty.test(name) || x.getName().contains(name)) &&
(isEmpty.test(token) || x.getSysPlatId().equals(platId(token)))
).map(x -> Kv.of("name", x.getName())
.set("comment", x.getComment())
.set("catalog", x.getCatalog())
.set("dbPlatId", x.getDbPlatId())
).collect(Collectors.toList());
jBean.setBody(list);
return jBean;
}
@@ -210,6 +200,29 @@ public class MetadataService extends BaseService { //arango
return JBean.by(0, "");
}
@RestMapping(name = "link_list", comment = "实体关系列表")
public JBean linkList() {
JBean jBean = new JBean();
List<MetaLink> links = MetaKit.getMetaLinks();
jBean.setBody(links);
return jBean;
}
@RestMapping(name = "link_list", comment = "实体关系列表")
public JBean linkSave(MetaLink link, @RestParam(name = "platToken") String token) {
if (link.getKey() != null) {
link.update();
} else {
link.save();
}
MetaKit.reload(MetaLink.class);
return JBean.OK;
}
@RestMapping(name = "plat_list", comment = "平台列表")
public JBean platList() {
JBean jBean = new JBean();

View File

@@ -1,16 +1,17 @@
package net.tccn.service;
import net.tccn.base.JBean;
import net.tccn.base.Kv;
import net.tccn.base.MetaKit;
import net.tccn.dbq.jdbc.api.DbAccount;
import net.tccn.dbq.jdbc.api.DbKit;
import net.tccn.dbq.table.Column;
import net.tccn.dbq.table.Table;
import net.tccn.meta.MetaTable;
import net.tccn.service.BaseService;
import org.redkale.net.http.RestMapping;
import org.redkale.net.http.RestService;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
@@ -38,30 +39,41 @@ public class _DbService extends BaseService {
}
@RestMapping(name = "table_list", comment = "数据库表列表")
public List<Table> tableList(String dbPlatId, String[] catalogs) {
public List<Table> tableList(String dbPlatId, String catalog, String[] tables) {
DbKit dbKit = MetaKit.getDbKit(dbPlatId);
StringBuffer sqlBuf = new StringBuffer("SELECT TABLE_NAME 'name',TABLE_COMMENT 'comment',table_schema 'catalog' FROM INFORMATION_SCHEMA.TABLES");
if (catalogs != null && catalogs.length > 0) {
sqlBuf.append(" WHERE TABLE_SCHEMA in (");
for (String catalog : catalogs) {
sqlBuf.append("'").append(catalog).append("',");
}
sqlBuf.deleteCharAt(sqlBuf.length() - 1);
sqlBuf.append(")");
}
List<Table> list = dbKit.findList(sqlBuf.toString(), Table.class);
String sql = tplKit.getTpl("db.table_list", Kv.of("catalog", catalog).set("tables", tables));
return dbKit.findList(sql, Table.class);
}
@RestMapping(ignore = true)
public List<Table> tableInfoList(String dbPlatId, String catalog, String[] tables) {
List<Table> list = new ArrayList<>(tables.length);
for (String table : tables) {
list.add(tableInfo(dbPlatId, catalog, table));
}
return list;
}
@RestMapping(name = "table_info", comment = "数据库表详情")
public JBean tableInfo(String dbPlatId, String catalog, String tableName) {
public JBean MetatableInfo(String dbPlatId, String catalog, String tableName) {
JBean jBean = new JBean();
try {
Table table = tableInfo(dbPlatId, catalog, tableName);
jBean.setBody(MetaTable.toAs(table));
} catch (Exception e) {
jBean.set(-1, "查询表信息失败");
new IllegalArgumentException("查询表信息失败", e);
}
return jBean;
}
@RestMapping(ignore = true, comment = "查询表信息")
public Table tableInfo(String dbPlatId, String catalog, String tableName) {
DbKit dbKit = MetaKit.getDbKit(dbPlatId);
String sql = String.format("SELECT TABLE_NAME 'name',TABLE_COMMENT 'comment',table_schema 'catalog' FROM INFORMATION_SCHEMA.TABLES where TABLE_NAME='%s'", tableName);
String sql = tplKit.getTpl("db.table_list", Kv.of("table", tableName));
String columnSql = String.format("SHOW FULL COLUMNS FROM %s.`%s`", catalog, tableName);
CompletableFuture<Table> tableFuture = CompletableFuture.supplyAsync(() -> dbKit.findfirst(sql, Table.class));
@@ -71,14 +83,11 @@ public class _DbService extends BaseService {
Table table = tableFuture.get();
table.setColumns(columnFuture.get());
//jBean.setBody(table);
jBean.setBody(MetaTable.toAs(table)); //todo: 将此转换提取到 单独方法中<依据六边形架构原则>
return table;
} catch (InterruptedException | ExecutionException e) {
jBean.set(-1, "查询表信息失败");
new IllegalArgumentException("查询表信息失败", e);
}
return jBean;
return null;
}
@RestMapping(name = "table_create", comment = "新建表[mysql]")
@@ -90,12 +99,4 @@ public class _DbService extends BaseService {
return jBean;
}
@RestMapping(ignore = true, comment = "查询表信息")
public List<Table> tableList(String dbPlatId, String catalog, String ... tables) {
//todo:
return null;
}
}

View File

@@ -37,7 +37,7 @@ public class _TableService extends BaseService {
String filePath,
//mysql {数据库连接账号、数据源id、数据库database数组}
String dbPlatId, String[] catalogs,
String dbPlatId, String catalog,
@RestParam(name = "platToken") String token) {
JBean jBean = new JBean();
@@ -46,7 +46,7 @@ public class _TableService extends BaseService {
jBean.setBody(fileService.data(filePath, token));
} else if ("mysql".equals(cate)){
List<Table> list = dbService.tableList(dbPlatId, catalogs);
List<Table> list = dbService.tableList(dbPlatId, catalog, null);
String[] tableArr = list.stream().map(Table::getName).toArray(String[]::new);
CompletableFuture<List<String>> hvFuture = tableExist(tableArr, token);
@@ -90,7 +90,7 @@ public class _TableService extends BaseService {
@RestParam(name = "platToken") String token) {
CompletableFuture<List<String>> hvfuture = tableExist(tableArr, token);
List<Table> tables = dbService.tableList(dbPlatId, catalog, tableArr);
List<Table> tables = dbService.tableInfoList(dbPlatId, catalog, tableArr);
try {
List<String> hvs = hvfuture.get();
@@ -106,6 +106,7 @@ public class _TableService extends BaseService {
metaTable.save();
}
});
MetaKit.reload(MetaTable.class);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}