数据库文档增加执行sql功能
This commit is contained in:
@@ -3,8 +3,11 @@ package com.zyplayer.doc.db.controller;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.zyplayer.doc.core.annotation.AuthMan;
|
||||
import com.zyplayer.doc.core.json.ResponseJson;
|
||||
import com.zyplayer.doc.data.repository.manage.entity.DbDatasource;
|
||||
import com.zyplayer.doc.data.service.manage.DbDatasourceService;
|
||||
import com.zyplayer.doc.db.controller.vo.DatabaseExportVo;
|
||||
import com.zyplayer.doc.db.controller.vo.TableColumnVo;
|
||||
import com.zyplayer.doc.db.controller.vo.TableColumnVo.TableInfoVo;
|
||||
@@ -17,12 +20,12 @@ import com.zyplayer.doc.db.framework.db.mapper.mysql.MysqlMapper;
|
||||
import com.zyplayer.doc.db.framework.json.DocDbResponseJson;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.mybatis.spring.SqlSessionTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
@@ -38,65 +41,69 @@ import java.util.stream.Collectors;
|
||||
@RestController
|
||||
@RequestMapping("/zyplayer-doc-db/doc-db")
|
||||
public class DatabaseDocController {
|
||||
|
||||
@Autowired
|
||||
|
||||
@Resource
|
||||
DatabaseRegistrationBean databaseRegistrationBean;
|
||||
|
||||
@Resource
|
||||
DbDatasourceService dbDatasourceService;
|
||||
|
||||
@PostMapping(value = "/getDataSourceList")
|
||||
public ResponseJson getDataSourceList() {
|
||||
List<DatabaseFactoryBean> factoryBeanList = databaseRegistrationBean.getDatabaseFactoryBeanList();
|
||||
List<DatabaseFactoryBean> dataSourceList = factoryBeanList.stream().map(val -> {
|
||||
QueryWrapper<DbDatasource> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("yn", 1);
|
||||
List<DbDatasource> datasourceList = dbDatasourceService.list(wrapper);
|
||||
List<DatabaseFactoryBean> dataSourceList = datasourceList.stream().map(val -> {
|
||||
DatabaseFactoryBean bean = new DatabaseFactoryBean();
|
||||
bean.setCnName(val.getCnName());
|
||||
bean.setHost(val.getHost());
|
||||
bean.setCnName(val.getName());
|
||||
bean.setId(val.getId());
|
||||
return bean;
|
||||
}).collect(Collectors.toList());
|
||||
return DocDbResponseJson.ok(dataSourceList);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping(value = "/getDatabaseList")
|
||||
public ResponseJson getDatabaseList(String host) {
|
||||
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapperByHost(host);
|
||||
public ResponseJson getDatabaseList(Long sourceId) {
|
||||
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapperById(sourceId);
|
||||
if (baseMapper == null) {
|
||||
return DocDbResponseJson.warn("未找到对应的数据库连接");
|
||||
}
|
||||
List<DatabaseInfoDto> dbNameDtoList = baseMapper.getDatabaseList();
|
||||
return DocDbResponseJson.ok(dbNameDtoList);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping(value = "/getTableList")
|
||||
public ResponseJson getTableList(String host, String dbName) {
|
||||
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapper(host, dbName);
|
||||
public ResponseJson getTableList(Long sourceId, String dbName) {
|
||||
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapperById(sourceId);
|
||||
if (baseMapper == null) {
|
||||
return DocDbResponseJson.warn("未找到对应的数据库连接");
|
||||
}
|
||||
List<TableInfoDto> dbTableList = baseMapper.getTableList(dbName);
|
||||
return DocDbResponseJson.ok(dbTableList);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping(value = "/getTableColumnList")
|
||||
public ResponseJson getTableColumnList(String host, String dbName, String tableName) {
|
||||
DatabaseFactoryBean databaseFactoryBean = databaseRegistrationBean.getDatabaseFactoryBean(host, dbName);
|
||||
public ResponseJson getTableColumnList(Long sourceId, String dbName, String tableName) {
|
||||
DatabaseFactoryBean databaseFactoryBean = databaseRegistrationBean.getFactoryById(sourceId);
|
||||
if (databaseFactoryBean == null) {
|
||||
return DocDbResponseJson.warn("未找到对应的数据库连接");
|
||||
}
|
||||
TableColumnVo tableColumnVo = this.getTableColumnVo(databaseFactoryBean, dbName, tableName);
|
||||
return DocDbResponseJson.ok(tableColumnVo);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping(value = "/getTableColumnDescList")
|
||||
public ResponseJson getTableColumnDescList(String host, String dbName, String tableName) {
|
||||
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapper(host, dbName);
|
||||
public ResponseJson getTableColumnDescList(Long sourceId, String tableName) {
|
||||
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapperById(sourceId);
|
||||
if (baseMapper == null) {
|
||||
return DocDbResponseJson.warn("未找到对应的数据库连接");
|
||||
}
|
||||
List<TableColumnDescDto> columnDescDto = baseMapper.getTableColumnDescList(tableName);
|
||||
return DocDbResponseJson.ok(columnDescDto);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping(value = "/getTableAndColumnBySearch")
|
||||
public ResponseJson getTableAndColumnBySearch(String host, String dbName, String searchText) {
|
||||
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapper(host, dbName);
|
||||
public ResponseJson getTableAndColumnBySearch(Long sourceId, String dbName, String searchText) {
|
||||
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapperById(sourceId);
|
||||
if (baseMapper == null) {
|
||||
return DocDbResponseJson.warn("未找到对应的数据库连接");
|
||||
}
|
||||
@@ -107,36 +114,36 @@ public class DatabaseDocController {
|
||||
List<QueryTableColumnDescDto> columnDescDto = baseMapper.getTableAndColumnBySearch(dbName, searchText);
|
||||
return DocDbResponseJson.ok(columnDescDto);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping(value = "/getTableDescList")
|
||||
public ResponseJson getTableDescList(String host, String dbName, String tableName) {
|
||||
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapper(host, dbName);
|
||||
public ResponseJson getTableDescList(Long sourceId, String tableName) {
|
||||
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapperById(sourceId);
|
||||
if (baseMapper == null) {
|
||||
return DocDbResponseJson.warn("未找到对应的数据库连接");
|
||||
}
|
||||
List<TableDescDto> columnDescDto = baseMapper.getTableDescList(tableName);
|
||||
return DocDbResponseJson.ok(columnDescDto);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping(value = "/updateTableDesc")
|
||||
public ResponseJson updateTableDesc(String host, String dbName, String tableName, String newDesc) {
|
||||
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapper(host, dbName);
|
||||
public ResponseJson updateTableDesc(Long sourceId, String dbName, String tableName, String newDesc) {
|
||||
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapperById(sourceId);
|
||||
if (baseMapper == null) {
|
||||
return DocDbResponseJson.warn("未找到对应的数据库连接");
|
||||
}
|
||||
baseMapper.updateTableDesc(dbName, tableName, newDesc);
|
||||
return DocDbResponseJson.ok();
|
||||
}
|
||||
|
||||
|
||||
@PostMapping(value = "/updateTableColumnDesc")
|
||||
public ResponseJson updateTableColumnDesc(String host, String dbName, String tableName, String columnName, String newDesc) {
|
||||
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapper(host, dbName);
|
||||
public ResponseJson updateTableColumnDesc(Long sourceId, String dbName, String tableName, String columnName, String newDesc) {
|
||||
BaseMapper baseMapper = databaseRegistrationBean.getBaseMapper(sourceId);
|
||||
if (baseMapper == null) {
|
||||
return DocDbResponseJson.warn("未找到对应的数据库连接");
|
||||
}
|
||||
ColumnInfoDto columnInfo = null;
|
||||
// mysql要同时修改类型默认值等,所以先查出来
|
||||
MysqlMapper mysqlMapper = databaseRegistrationBean.getBaseMapper(host, dbName, MysqlMapper.class);
|
||||
MysqlMapper mysqlMapper = databaseRegistrationBean.getBaseMapper(sourceId, MysqlMapper.class);
|
||||
if (mysqlMapper != null) {
|
||||
columnInfo = mysqlMapper.getColumnInfo(dbName, tableName, columnName);
|
||||
String isNullable = Optional.ofNullable(columnInfo.getIsNullable()).orElse("");
|
||||
@@ -155,11 +162,11 @@ public class DatabaseDocController {
|
||||
}
|
||||
|
||||
@GetMapping(value = "/exportDatabase")
|
||||
public ResponseJson exportDatabase(HttpServletResponse response, String host, String dbName, String tableNames) {
|
||||
public ResponseJson exportDatabase(HttpServletResponse response, Long sourceId, String dbName, String tableNames) {
|
||||
if (StringUtils.isBlank(tableNames)) {
|
||||
return DocDbResponseJson.warn("请选择需要导出的表");
|
||||
}
|
||||
DatabaseFactoryBean databaseFactoryBean = databaseRegistrationBean.getDatabaseFactoryBean(host, dbName);
|
||||
DatabaseFactoryBean databaseFactoryBean = databaseRegistrationBean.getFactoryById(sourceId);
|
||||
if (databaseFactoryBean == null) {
|
||||
return DocDbResponseJson.warn("未找到对应的数据库连接");
|
||||
}
|
||||
@@ -203,7 +210,7 @@ public class DatabaseDocController {
|
||||
// 字段注释
|
||||
for (TableColumnDescDto descDto : columnDescList) {
|
||||
TableColumnDescDto tempDesc = columnMap.get(descDto.getName());
|
||||
if(tempDesc != null) {
|
||||
if (tempDesc != null) {
|
||||
tempDesc.setDescription(descDto.getDescription());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,10 +67,17 @@ public class DbDatasourceController {
|
||||
dbDatasource.setCreateUserId(null);
|
||||
dbDatasource.setCreateUserName(null);
|
||||
Long sourceId = Optional.ofNullable(dbDatasource.getId()).orElse(0L);
|
||||
DbDatasource dbDatasourceSel = dbDatasource;
|
||||
if (sourceId > 0) {
|
||||
dbDatasourceSel = dbDatasourceService.getById(dbDatasource.getId());
|
||||
dbDatasourceService.updateById(dbDatasource);
|
||||
} else {
|
||||
DocUserDetails currentUser = DocUserUtil.getCurrentUser();
|
||||
dbDatasource.setCreateTime(new Date());
|
||||
dbDatasource.setCreateUserId(currentUser.getUserId());
|
||||
dbDatasource.setCreateUserName(currentUser.getUsername());
|
||||
dbDatasource.setYn(1);
|
||||
dbDatasourceService.save(dbDatasource);
|
||||
}
|
||||
DbDatasource dbDatasourceSel = dbDatasourceService.getById(dbDatasource.getId());
|
||||
List<DatabaseFactoryBean> newFactoryBeanList = new LinkedList<>();
|
||||
List<DatabaseFactoryBean> databaseFactoryBeanList = databaseRegistrationBean.getDatabaseFactoryBeanList();
|
||||
for (DatabaseFactoryBean factoryBean : databaseFactoryBeanList) {
|
||||
@@ -92,20 +99,9 @@ public class DbDatasourceController {
|
||||
newFactoryBeanList.add(databaseFactoryBean);
|
||||
}
|
||||
databaseRegistrationBean.setDatabaseFactoryBeanList(newFactoryBeanList);
|
||||
|
||||
if (databaseFactoryBean == null) {
|
||||
return DocDbResponseJson.warn("创建数据源失败,请检查配置是否正确");
|
||||
}
|
||||
if (sourceId > 0) {
|
||||
dbDatasourceService.updateById(dbDatasource);
|
||||
} else {
|
||||
DocUserDetails currentUser = DocUserUtil.getCurrentUser();
|
||||
dbDatasource.setCreateTime(new Date());
|
||||
dbDatasource.setCreateUserId(currentUser.getUserId());
|
||||
dbDatasource.setCreateUserName(currentUser.getUsername());
|
||||
dbDatasource.setYn(1);
|
||||
dbDatasourceService.save(dbDatasource);
|
||||
}
|
||||
return DocDbResponseJson.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.zyplayer.doc.db.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.zyplayer.doc.core.annotation.AuthMan;
|
||||
import com.zyplayer.doc.core.json.ResponseJson;
|
||||
import com.zyplayer.doc.core.util.StringUtil;
|
||||
import com.zyplayer.doc.db.framework.db.mapper.base.ExecuteResult;
|
||||
import com.zyplayer.doc.db.framework.db.mapper.base.SqlExecutor;
|
||||
import com.zyplayer.doc.db.framework.json.DocDbResponseJson;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* sql执行器
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年8月18日
|
||||
*/
|
||||
@AuthMan
|
||||
@RestController
|
||||
@RequestMapping("/zyplayer-doc-db/executor")
|
||||
public class DbSqlExecutorController {
|
||||
|
||||
@Resource
|
||||
SqlExecutor sqlExecutor;
|
||||
|
||||
@PostMapping(value = "/execute")
|
||||
public ResponseJson execute(Long sourceId, String executeId, String sql, String params) {
|
||||
Map<String, Object> paramMap = JSON.parseObject(params);
|
||||
try {
|
||||
ExecuteResult executeResult = sqlExecutor.execute(sourceId, executeId, sql, paramMap);
|
||||
String resultJsonStr = JSON.toJSONString(executeResult, SerializerFeature.WriteMapNullValue);
|
||||
return DocDbResponseJson.ok(resultJsonStr);
|
||||
} catch (Exception e) {
|
||||
return DocDbResponseJson.warn(StringUtil.getException(e));
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/cancel")
|
||||
public ResponseJson cancel(String executeId) {
|
||||
sqlExecutor.cancel(executeId);
|
||||
return DocDbResponseJson.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,15 +9,16 @@ import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class ApplicationListenerBean implements ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
@javax.annotation.Resource
|
||||
@Resource
|
||||
DatabaseRegistrationBean databaseRegistrationBean;
|
||||
@javax.annotation.Resource
|
||||
@Resource
|
||||
DbDatasourceService dbDatasourceService;
|
||||
|
||||
private volatile static boolean IS_INIT = false;
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package com.zyplayer.doc.db.framework.db.bean;
|
||||
|
||||
import com.zyplayer.doc.db.framework.db.bean.DatabaseFactoryBean.DatabaseProduct;
|
||||
import com.zyplayer.doc.db.framework.db.mapper.base.BaseMapper;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.mybatis.spring.SqlSessionTemplate;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 需要声明注入的对象,只需要设置dbConfigList即可
|
||||
* databaseFactoryBeanList是后面生成的
|
||||
*
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2018年8月8日
|
||||
*/
|
||||
@@ -22,59 +21,51 @@ public class DatabaseRegistrationBean {
|
||||
private List<DbConfigBean> dbConfigList = new LinkedList<>();
|
||||
// 描述连接信息的对象列表
|
||||
private List<DatabaseFactoryBean> databaseFactoryBeanList = new LinkedList<>();
|
||||
|
||||
|
||||
public List<DatabaseFactoryBean> getDatabaseFactoryBeanList() {
|
||||
return databaseFactoryBeanList;
|
||||
}
|
||||
|
||||
|
||||
public void setDatabaseFactoryBeanList(List<DatabaseFactoryBean> databaseFactoryBeanList) {
|
||||
this.databaseFactoryBeanList = databaseFactoryBeanList;
|
||||
}
|
||||
|
||||
public DatabaseFactoryBean getDatabaseFactoryBean(String host, String dbName) {
|
||||
if (StringUtils.isBlank(dbName)) {
|
||||
return null;
|
||||
}
|
||||
DatabaseFactoryBean resultBean = null;
|
||||
for (DatabaseFactoryBean databaseFactoryBean : databaseFactoryBeanList) {
|
||||
if (host.equalsIgnoreCase(databaseFactoryBean.getHost())) {
|
||||
if (dbName.equalsIgnoreCase(databaseFactoryBean.getDbName())) {
|
||||
return databaseFactoryBean;
|
||||
}
|
||||
if (databaseFactoryBean.getDatabaseProduct() == DatabaseProduct.MYSQL) {
|
||||
resultBean = databaseFactoryBean;
|
||||
}
|
||||
}
|
||||
}
|
||||
return resultBean;
|
||||
public BaseMapper getBaseMapper(Long sourceId) {
|
||||
return getBaseMapper(sourceId, BaseMapper.class);
|
||||
}
|
||||
|
||||
public BaseMapper getBaseMapper(String host, String dbName) {
|
||||
return getBaseMapper(host, dbName, BaseMapper.class);
|
||||
}
|
||||
|
||||
public <T> T getBaseMapper(String host, String dbName, Class<T> cls) {
|
||||
DatabaseFactoryBean factoryBean = getDatabaseFactoryBean(host, dbName);
|
||||
public <T> T getBaseMapper(Long sourceId, Class<T> cls) {
|
||||
DatabaseFactoryBean factoryBean = getFactoryById(sourceId);
|
||||
if (factoryBean != null) {
|
||||
SqlSessionTemplate sessionTemplate = factoryBean.getSqlSessionTemplate();
|
||||
try {
|
||||
return sessionTemplate.getMapper(cls);
|
||||
} catch (Exception e) {}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public BaseMapper getBaseMapperByHost(String host) {
|
||||
if (StringUtils.isBlank(host)) {
|
||||
|
||||
public DatabaseFactoryBean getFactoryById(Long sourceId) {
|
||||
for (DatabaseFactoryBean databaseFactoryBean : databaseFactoryBeanList) {
|
||||
if (Objects.equals(databaseFactoryBean.getId(), sourceId)) {
|
||||
return databaseFactoryBean;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public BaseMapper getBaseMapperById(Long sourceId) {
|
||||
DatabaseFactoryBean databaseFactoryBean = this.getFactoryById(sourceId);
|
||||
if (databaseFactoryBean == null) {
|
||||
return null;
|
||||
}
|
||||
for (DatabaseFactoryBean databaseFactoryBean : databaseFactoryBeanList) {
|
||||
if (host.equalsIgnoreCase(databaseFactoryBean.getHost())) {
|
||||
try {
|
||||
SqlSessionTemplate sessionTemplate = databaseFactoryBean.getSqlSessionTemplate();
|
||||
return sessionTemplate.getMapper(BaseMapper.class);
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
try {
|
||||
SqlSessionTemplate sessionTemplate = databaseFactoryBean.getSqlSessionTemplate();
|
||||
return sessionTemplate.getMapper(BaseMapper.class);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -86,4 +77,4 @@ public class DatabaseRegistrationBean {
|
||||
public void setDbConfigList(List<DbConfigBean> dbConfigList) {
|
||||
this.dbConfigList = dbConfigList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.zyplayer.doc.db.framework.db.interceptor;
|
||||
|
||||
import org.apache.ibatis.mapping.BoundSql;
|
||||
import org.apache.ibatis.mapping.ParameterMapping;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class SqlLogUtil {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SqlLogUtil.class);
|
||||
|
||||
private static String getParameterValue(Object obj) {
|
||||
String value;
|
||||
if (obj instanceof String) {
|
||||
value = "'" + obj.toString() + "'";
|
||||
} else if (obj instanceof Date) {
|
||||
DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
|
||||
value = "'" + formatter.format(obj) + "'";
|
||||
} else {
|
||||
value = (obj == null) ? "'null'" : obj.toString();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static String getSqlString(Map<String, Object> paramMap, BoundSql boundSql) {
|
||||
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
|
||||
StringBuilder sqlSb = new StringBuilder(boundSql.getSql().replaceAll("[\\s]+", " "));
|
||||
int fromIndex = 0;
|
||||
if (parameterMappings.size() > 0) {
|
||||
for (ParameterMapping parameterMapping : parameterMappings) {
|
||||
String propertyName = parameterMapping.getProperty();
|
||||
Object obj = paramMap.get(propertyName);
|
||||
fromIndex = replacePlaceholder(sqlSb, fromIndex, getParameterValue(obj));
|
||||
}
|
||||
}
|
||||
return sqlSb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换?占位符
|
||||
*
|
||||
* @param sql
|
||||
* @param fromIndex
|
||||
* @param replaceStr
|
||||
* @return
|
||||
* @author 暮光:城中城
|
||||
* @since 2018年10月27日
|
||||
*/
|
||||
private static int replacePlaceholder(StringBuilder sql, int fromIndex, String replaceStr) {
|
||||
int index = sql.indexOf("?", fromIndex);
|
||||
if (index >= 0) {
|
||||
sql.replace(index, index + 1, replaceStr);
|
||||
}
|
||||
return index + replaceStr.length();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.zyplayer.doc.db.framework.db.mapper.base;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 执行结果
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年8月18日
|
||||
*/
|
||||
public class ExecuteResult {
|
||||
private int updateCount;
|
||||
private List<Map<String, Object>> result;
|
||||
|
||||
public ExecuteResult() {
|
||||
this.updateCount = 0;
|
||||
this.result = Collections.emptyList();
|
||||
}
|
||||
|
||||
public ExecuteResult(int updateCount, List<Map<String, Object>> result) {
|
||||
this.updateCount = updateCount;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public int getUpdateCount() {
|
||||
return updateCount;
|
||||
}
|
||||
|
||||
public void setUpdateCount(int updateCount) {
|
||||
this.updateCount = updateCount;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(List<Map<String, Object>> result) {
|
||||
this.result = result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.zyplayer.doc.db.framework.db.mapper.base;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 执行结果回调
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年8月18日
|
||||
*/
|
||||
public interface ResultHandler {
|
||||
|
||||
void handleResult(Map<String, Object> resultMap);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package com.zyplayer.doc.db.framework.db.mapper.base;
|
||||
|
||||
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
||||
import com.zyplayer.doc.db.framework.db.bean.DatabaseFactoryBean;
|
||||
import com.zyplayer.doc.db.framework.db.bean.DatabaseRegistrationBean;
|
||||
import com.zyplayer.doc.db.framework.db.interceptor.SqlLogUtil;
|
||||
import org.apache.ibatis.builder.SqlSourceBuilder;
|
||||
import org.apache.ibatis.builder.StaticSqlSource;
|
||||
import org.apache.ibatis.mapping.BoundSql;
|
||||
import org.apache.ibatis.mapping.ParameterMapping;
|
||||
import org.apache.ibatis.parsing.GenericTokenParser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* sql执行器
|
||||
*
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年8月18日
|
||||
*/
|
||||
@Repository
|
||||
public class SqlExecutor {
|
||||
private static Logger logger = LoggerFactory.getLogger(SqlExecutor.class);
|
||||
|
||||
@Resource
|
||||
DatabaseRegistrationBean databaseRegistrationBean;
|
||||
|
||||
// 执行中的PreparedStatement信息,用于强制取消执行
|
||||
private static final Map<String, PreparedStatement> statementMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 取消执行
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年8月18日
|
||||
*/
|
||||
public void cancel(String executeId) {
|
||||
PreparedStatement preparedStatement = statementMap.remove(executeId);
|
||||
try {
|
||||
preparedStatement.cancel();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行sql,返回结果
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年8月18日
|
||||
*/
|
||||
public ExecuteResult execute(Long datasourceId, String executeId, String sql, Map<String, Object> paramMap) {
|
||||
DatabaseFactoryBean factoryBean = databaseRegistrationBean.getFactoryById(datasourceId);
|
||||
return this.execute(factoryBean, executeId, sql, paramMap, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行sql,可通过handler回调每一行的结果
|
||||
* @author 暮光:城中城
|
||||
* @since 2019年8月18日
|
||||
*/
|
||||
public ExecuteResult execute(DatabaseFactoryBean factoryBean, String executeId, String sql, Map<String, Object> paramMap, ResultHandler handler) {
|
||||
if (factoryBean == null) {
|
||||
return new ExecuteResult();
|
||||
}
|
||||
// 组装参数
|
||||
GenericTokenParser parser = new GenericTokenParser("${", "}", content -> {
|
||||
Object o = paramMap.get(content);
|
||||
return (o == null) ? null : String.valueOf(o);
|
||||
});
|
||||
sql = parser.parse(sql);
|
||||
SqlSourceBuilder sqlSourceBuilder = new SqlSourceBuilder(new MybatisConfiguration());
|
||||
StaticSqlSource parse = (StaticSqlSource) sqlSourceBuilder.parse(sql, Object.class, paramMap);
|
||||
BoundSql boundSql = parse.getBoundSql(new Object());
|
||||
sql = boundSql.getSql();
|
||||
logger.info("sql ==> {}", SqlLogUtil.getSqlString(paramMap, boundSql));
|
||||
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
|
||||
PreparedStatement preparedStatement = null;
|
||||
// 执行查询
|
||||
try {
|
||||
Connection connection = factoryBean.getDataSource().getConnection();
|
||||
preparedStatement = connection.prepareStatement(sql);
|
||||
// 设置当前的PreparedStatement
|
||||
statementMap.put(executeId, preparedStatement);
|
||||
for (int i = 0; i < parameterMappings.size(); i++) {
|
||||
preparedStatement.setObject(i + 1, paramMap.get(parameterMappings.get(i).getProperty()));
|
||||
}
|
||||
preparedStatement.execute();
|
||||
// 查询的结果集
|
||||
ResultSet resultSet = preparedStatement.getResultSet();
|
||||
List<Map<String, Object>> resultList = new LinkedList<>();
|
||||
if (resultSet != null) {
|
||||
while (resultSet.next()) {
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
ResultSetMetaData metaData = resultSet.getMetaData();
|
||||
for (int i = 0; i < metaData.getColumnCount(); i++) {
|
||||
resultMap.put(metaData.getColumnName(i + 1), resultSet.getObject(i + 1));
|
||||
}
|
||||
if (handler != null) {
|
||||
handler.handleResult(resultMap);
|
||||
} else {
|
||||
resultList.add(resultMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 更新的数量
|
||||
int updateCount = preparedStatement.getUpdateCount();
|
||||
updateCount = (updateCount < 0) ? 0 : updateCount;
|
||||
return new ExecuteResult(updateCount, resultList);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
statementMap.remove(executeId);
|
||||
try {
|
||||
if (preparedStatement != null && !preparedStatement.isClosed()) {
|
||||
preparedStatement.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("关闭Statement失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user