commit:支持activiti

This commit is contained in:
Jerry
2021-10-20 17:43:53 +08:00
parent b772e75de6
commit 00cc13b87d
861 changed files with 219314 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
<?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>common</artifactId>
<groupId>com.flow.demo</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>common-online</artifactId>
<version>1.0.0</version>
<name>common-online</name>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.flow.demo</groupId>
<artifactId>common-core</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.flow.demo</groupId>
<artifactId>common-datafilter</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.flow.demo</groupId>
<artifactId>common-redis</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.flow.demo</groupId>
<artifactId>common-sequence</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.flow.demo</groupId>
<artifactId>common-log</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>

View File

@@ -0,0 +1,13 @@
package com.flow.demo.common.online.config;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
/**
* common-online模块的自动配置引导类。
*
* @author Jerry
* @date 2021-06-06
*/
@EnableConfigurationProperties({OnlineProperties.class})
public class OnlineAutoConfig {
}

View File

@@ -0,0 +1,30 @@
package com.flow.demo.common.online.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 在线表单的配置对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
@ConfigurationProperties(prefix = "common-online")
public class OnlineProperties {
/**
* 仅以该前缀开头的数据表才会成为动态表单的候选数据表,如: zz_。如果为空则所有表均可被选。
*/
private String tablePrefix;
/**
* 在线表单业务操作的URL前缀。
*/
private String operationUrlPrefix;
/**
* 上传文件的根路径。
*/
private String uploadFileBaseDir;
}

View File

@@ -0,0 +1,786 @@
package com.flow.demo.common.online.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.flow.demo.common.core.annotation.MyRequestBody;
import com.flow.demo.common.core.constant.ErrorCodeEnum;
import com.flow.demo.common.core.object.*;
import com.flow.demo.common.core.util.ContextUtil;
import com.flow.demo.common.core.util.MyCommonUtil;
import com.flow.demo.common.core.util.MyPageUtil;
import com.flow.demo.common.online.util.OnlineOperationHelper;
import com.flow.demo.common.online.dto.OnlineFilterDto;
import com.flow.demo.common.online.model.*;
import com.flow.demo.common.online.model.constant.DictType;
import com.flow.demo.common.online.model.constant.RelationType;
import com.flow.demo.common.online.object.ColumnData;
import com.flow.demo.common.online.service.*;
import com.flow.demo.common.online.util.OnlineConstant;
import com.github.pagehelper.page.PageMethod;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
/**
* 在线操作接口的控制器类。
*
* @author Jerry
* @date 2021-06-06
*/
@Slf4j
@RestController
@ConditionalOnProperty(name = "common-online.operationEnabled", havingValue = "true")
@RequestMapping("${common-online.operationUrlPrefix}/onlineOperation")
public class OnlineOperationController {
@Autowired
private OnlineOperationService onlineOperationService;
@Autowired
private OnlineDictService onlineDictService;
@Autowired
private OnlineDatasourceService onlineDatasourceService;
@Autowired
private OnlineDatasourceRelationService onlineDatasourceRelationService;
@Autowired
private OnlineTableService onlineTableService;
@Autowired
private OnlineOperationHelper onlineOperationHelper;
/**
* 新增数据接口。
*
* @param datasourceVariableName 数据源名称。
* @param datasourceId 主表的数据源Id。
* @param masterData 主表新增数据。
* @param slaveData 一对多从表新增数据列表。
* @return 应答结果。
*/
@PostMapping("/addDatasource/{datasourceVariableName}")
public ResponseResult<Void> addDatasource(
@PathVariable("datasourceVariableName") String datasourceVariableName,
@MyRequestBody(required = true) Long datasourceId,
@MyRequestBody(required = true) JSONObject masterData,
@MyRequestBody JSONObject slaveData) throws IOException {
String errorMessage;
// 验证数据源的合法性,同时获取主表对象。
ResponseResult<OnlineDatasource> datasourceResult =
onlineOperationHelper.verifyAndGetDatasource(datasourceId);
if (!datasourceResult.isSuccess()) {
return ResponseResult.errorFrom(datasourceResult);
}
OnlineDatasource datasource = datasourceResult.getData();
if (!datasource.getVariableName().equals(datasourceVariableName)) {
ContextUtil.getHttpResponse().setStatus(HttpServletResponse.SC_FORBIDDEN);
return ResponseResult.error(ErrorCodeEnum.NO_OPERATION_PERMISSION);
}
OnlineTable masterTable = datasource.getMasterTable();
ResponseResult<List<ColumnData>> columnDataListResult =
onlineOperationHelper.buildTableData(masterTable, masterData, false, null);
if (!columnDataListResult.isSuccess()) {
return ResponseResult.errorFrom(columnDataListResult);
}
if (slaveData == null) {
onlineOperationService.saveNew(masterTable, columnDataListResult.getData());
} else {
ResponseResult<Map<OnlineDatasourceRelation, List<List<ColumnData>>>> slaveDataListResult =
onlineOperationHelper.buildSlaveDataList(datasourceId, slaveData);
if (!slaveDataListResult.isSuccess()) {
return ResponseResult.errorFrom(slaveDataListResult);
}
onlineOperationService.saveNewAndSlaveRelation(
masterTable, columnDataListResult.getData(), slaveDataListResult.getData());
}
return ResponseResult.success();
}
/**
* 新增一对多从表数据接口。
*
* @param datasourceVariableName 数据源名称。
* @param datasourceId 主表的数据源Id。
* @param relationId 一对多的关联Id。
* @param slaveData 一对多从表的新增数据列表。
* @return 应答结果。
*/
@PostMapping("/addOneToManyRelation/{datasourceVariableName}")
public ResponseResult<Void> addOneToManyRelation(
@PathVariable("datasourceVariableName") String datasourceVariableName,
@MyRequestBody(required = true) Long datasourceId,
@MyRequestBody(required = true) Long relationId,
@MyRequestBody(required = true) JSONObject slaveData) {
String errorMessage;
OnlineDatasource datasource = onlineDatasourceService.getById(datasourceId);
if (datasource == null) {
errorMessage = "数据验证失败数据源Id并不存在";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
if (!datasource.getVariableName().equals(datasourceVariableName)) {
ContextUtil.getHttpResponse().setStatus(HttpServletResponse.SC_FORBIDDEN);
return ResponseResult.error(ErrorCodeEnum.NO_OPERATION_PERMISSION);
}
ResponseResult<OnlineDatasourceRelation> relationResult =
onlineOperationHelper.verifyAndGetOneToManyRelation(datasourceId, relationId);
if (!relationResult.isSuccess()) {
return ResponseResult.errorFrom(relationResult);
}
OnlineDatasourceRelation relation = relationResult.getData();
OnlineTable slaveTable = relation.getSlaveTable();
// 拆解主表和一对多关联从表的输入参数,并构建出数据表的待插入数据列表。
ResponseResult<List<ColumnData>> columnDataListResult =
onlineOperationHelper.buildTableData(slaveTable, slaveData, false, null);
if (!columnDataListResult.isSuccess()) {
return ResponseResult.errorFrom(columnDataListResult);
}
onlineOperationService.saveNew(slaveTable, columnDataListResult.getData());
return ResponseResult.success();
}
/**
* 更新主数据接口。
*
* @param datasourceVariableName 数据源名称。
* @param datasourceId 主表数据源Id。
* @param masterData 表数据。这里没有包含的字段将视为NULL。
* @return 应该结果。
*/
@PostMapping("/updateDatasource/{datasourceVariableName}")
public ResponseResult<Void> updateDatasource(
@PathVariable("datasourceVariableName") String datasourceVariableName,
@MyRequestBody(required = true) Long datasourceId,
@MyRequestBody(required = true) JSONObject masterData) {
String errorMessage;
ResponseResult<OnlineDatasource> datasourceResult =
onlineOperationHelper.verifyAndGetDatasource(datasourceId);
if (!datasourceResult.isSuccess()) {
return ResponseResult.errorFrom(datasourceResult);
}
OnlineDatasource datasource = datasourceResult.getData();
if (!datasource.getVariableName().equals(datasourceVariableName)) {
ContextUtil.getHttpResponse().setStatus(HttpServletResponse.SC_FORBIDDEN);
return ResponseResult.error(ErrorCodeEnum.NO_OPERATION_PERMISSION);
}
OnlineTable masterTable = datasource.getMasterTable();
ResponseResult<List<ColumnData>> columnDataListResult =
onlineOperationHelper.buildTableData(masterTable, masterData, true, null);
if (!columnDataListResult.isSuccess()) {
return ResponseResult.errorFrom(columnDataListResult);
}
if (!onlineOperationService.update(masterTable, columnDataListResult.getData())) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
/**
* 更新一对多关联数据接口。
*
* @param datasourceVariableName 数据源名称。
* @param datasourceId 主表数据源Id。
* @param relationId 一对多关联Id。
* @param slaveData 一对多关联从表数据。这里没有包含的字段将视为NULL。
* @return 应该结果。
*/
@PostMapping("/updateOneToManyRelation/{datasourceVariableName}")
public ResponseResult<Void> updateOneToManyRelation(
@PathVariable("datasourceVariableName") String datasourceVariableName,
@MyRequestBody(required = true) Long datasourceId,
@MyRequestBody(required = true) Long relationId,
@MyRequestBody(required = true) JSONObject slaveData) {
String errorMessage;
OnlineDatasource datasource = onlineDatasourceService.getById(datasourceId);
if (datasource == null) {
errorMessage = "数据验证失败数据源Id并不存在";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
if (!datasource.getVariableName().equals(datasourceVariableName)) {
ContextUtil.getHttpResponse().setStatus(HttpServletResponse.SC_FORBIDDEN);
return ResponseResult.error(ErrorCodeEnum.NO_OPERATION_PERMISSION);
}
ResponseResult<OnlineDatasourceRelation> relationResult =
onlineOperationHelper.verifyAndGetOneToManyRelation(datasourceId, relationId);
if (!relationResult.isSuccess()) {
return ResponseResult.errorFrom(relationResult);
}
OnlineTable slaveTable = relationResult.getData().getSlaveTable();
ResponseResult<List<ColumnData>> columnDataListResult =
onlineOperationHelper.buildTableData(slaveTable, slaveData, true, null);
if (!columnDataListResult.isSuccess()) {
return ResponseResult.errorFrom(columnDataListResult);
}
if (!onlineOperationService.update(slaveTable, columnDataListResult.getData())) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
/**
* 删除主数据接口。
*
* @param datasourceVariableName 数据源名称。
* @param datasourceId 主表数据源Id。
* @param dataId 待删除的数据表主键Id。
* @return 应该结果。
*/
@PostMapping("/deleteDatasource/{datasourceVariableName}")
public ResponseResult<Void> deleteDatasource(
@PathVariable("datasourceVariableName") String datasourceVariableName,
@MyRequestBody(required = true) Long datasourceId,
@MyRequestBody(required = true) String dataId) {
String errorMessage;
ResponseResult<OnlineDatasource> datasourceResult =
onlineOperationHelper.verifyAndGetDatasource(datasourceId);
if (!datasourceResult.isSuccess()) {
return ResponseResult.errorFrom(datasourceResult);
}
OnlineDatasource datasource = datasourceResult.getData();
if (!datasource.getVariableName().equals(datasourceVariableName)) {
ContextUtil.getHttpResponse().setStatus(HttpServletResponse.SC_FORBIDDEN);
return ResponseResult.error(ErrorCodeEnum.NO_OPERATION_PERMISSION);
}
OnlineTable masterTable = datasource.getMasterTable();
ResponseResult<List<OnlineDatasourceRelation>> relationListResult =
onlineOperationHelper.verifyAndGetRelationList(datasourceId, RelationType.ONE_TO_MANY);
if (!relationListResult.isSuccess()) {
return ResponseResult.errorFrom(relationListResult);
}
List<OnlineDatasourceRelation> relationList = relationListResult.getData();
if (!onlineOperationService.delete(masterTable, relationList, dataId)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
/**
* 删除一对多关联表单条数据接口。
*
* @param datasourceVariableName 数据源名称。
* @param datasourceId 主表数据源Id。
* @param relationId 一对多关联Id。
* @param dataId 一对多关联表主键Id。
* @return 应该结果。
*/
@PostMapping("/deleteOneToManyRelation/{datasourceVariableName}")
public ResponseResult<Void> deleteOneToManyRelation(
@PathVariable("datasourceVariableName") String datasourceVariableName,
@MyRequestBody(required = true) Long datasourceId,
@MyRequestBody(required = true) Long relationId,
@MyRequestBody(required = true) String dataId) {
String errorMessage;
OnlineDatasource datasource = onlineDatasourceService.getById(datasourceId);
if (datasource == null) {
errorMessage = "数据验证失败数据源Id并不存在";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
if (!datasource.getVariableName().equals(datasourceVariableName)) {
ContextUtil.getHttpResponse().setStatus(HttpServletResponse.SC_FORBIDDEN);
return ResponseResult.error(ErrorCodeEnum.NO_OPERATION_PERMISSION);
}
ResponseResult<OnlineDatasourceRelation> relationResult =
onlineOperationHelper.verifyAndGetOneToManyRelation(datasourceId, relationId);
if (!relationResult.isSuccess()) {
return ResponseResult.errorFrom(relationResult);
}
OnlineDatasourceRelation relation = relationResult.getData();
if (!onlineOperationService.delete(relation.getSlaveTable(), null, dataId)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
/**
* 根据数据源Id为动态表单查询数据详情。
*
* @param datasourceVariableName 数据源名称。
* @param datasourceId 数据源Id。
* @param dataId 数据主键Id。
* @return 详情结果。
*/
@GetMapping("/viewByDatasourceId/{datasourceVariableName}")
public ResponseResult<Map<String, Object>> viewByDatasourceId(
@PathVariable("datasourceVariableName") String datasourceVariableName,
@RequestParam Long datasourceId,
@RequestParam String dataId) {
String errorMessage;
// 验证数据源及其关联
ResponseResult<OnlineDatasource> datasourceResult =
onlineOperationHelper.verifyAndGetDatasource(datasourceId);
if (!datasourceResult.isSuccess()) {
return ResponseResult.errorFrom(datasourceResult);
}
OnlineDatasource datasource = datasourceResult.getData();
if (!datasource.getVariableName().equals(datasourceVariableName)) {
ContextUtil.getHttpResponse().setStatus(HttpServletResponse.SC_FORBIDDEN);
return ResponseResult.error(ErrorCodeEnum.NO_OPERATION_PERMISSION);
}
OnlineTable masterTable = datasource.getMasterTable();
ResponseResult<List<OnlineDatasourceRelation>> relationListResult =
onlineOperationHelper.verifyAndGetRelationList(datasourceId, null);
if (!relationListResult.isSuccess()) {
return ResponseResult.errorFrom(relationListResult);
}
List<OnlineDatasourceRelation> allRelationList = relationListResult.getData();
List<OnlineDatasourceRelation> oneToOneRelationList = allRelationList.stream()
.filter(r -> r.getRelationType().equals(RelationType.ONE_TO_ONE)).collect(Collectors.toList());
Map<String, Object> result =
onlineOperationService.getMasterData(masterTable, oneToOneRelationList, allRelationList, dataId);
return ResponseResult.success(result);
}
/**
* 根据数据源关联Id为动态表单查询数据详情。
*
* @param datasourceVariableName 数据源名称。
* @param datasourceId 数据源Id。
* @param relationId 一对多关联Id。
* @param dataId 一对多关联数据主键Id。
* @return 详情结果。
*/
@GetMapping("/viewByOneToManyRelationId/{datasourceVariableName}")
public ResponseResult<Map<String, Object>> viewByOneToManyRelationId(
@PathVariable("datasourceVariableName") String datasourceVariableName,
@RequestParam Long datasourceId,
@RequestParam Long relationId,
@RequestParam String dataId) {
String errorMessage;
OnlineDatasource datasource = onlineDatasourceService.getById(datasourceId);
if (datasource == null) {
errorMessage = "数据验证失败数据源Id并不存在";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
if (!datasource.getVariableName().equals(datasourceVariableName)) {
ContextUtil.getHttpResponse().setStatus(HttpServletResponse.SC_FORBIDDEN);
return ResponseResult.error(ErrorCodeEnum.NO_OPERATION_PERMISSION);
}
ResponseResult<OnlineDatasourceRelation> relationResult =
onlineOperationHelper.verifyAndGetOneToManyRelation(datasourceId, relationId);
if (!relationResult.isSuccess()) {
return ResponseResult.errorFrom(relationResult);
}
OnlineDatasourceRelation relation = relationResult.getData();
Map<String, Object> result = onlineOperationService.getSlaveData(relation, dataId);
return ResponseResult.success(result);
}
/**
* 为数据源主表字段下载文件。
*
* @param datasourceVariableName 数据源名称。
* @param datasourceId 数据源Id。
* @param dataId 附件所在记录的主键Id。
* @param fieldName 数据表字段名。
* @param asImage 是否为图片文件。
* @param response Http 应答对象。
*/
@GetMapping("/downloadDatasource/{datasourceVariableName}")
public void downloadDatasource(
@PathVariable("datasourceVariableName") String datasourceVariableName,
@RequestParam Long datasourceId,
@RequestParam(required = false) String dataId,
@RequestParam String fieldName,
@RequestParam String filename,
@RequestParam Boolean asImage,
HttpServletResponse response) throws Exception {
if (MyCommonUtil.existBlankArgument(fieldName, filename, asImage)) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}
ResponseResult<OnlineDatasource> datasourceResult =
onlineOperationHelper.verifyAndGetDatasource(datasourceId);
if (!datasourceResult.isSuccess()) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN, ResponseResult.errorFrom(datasourceResult));
return;
}
OnlineDatasource datasource = datasourceResult.getData();
if (!datasource.getVariableName().equals(datasourceVariableName)) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
ResponseResult.error(ErrorCodeEnum.NO_OPERATION_PERMISSION));
return;
}
OnlineTable masterTable = datasource.getMasterTable();
onlineOperationHelper.doDownload(masterTable, dataId, fieldName, filename, asImage, response);
}
/**
* 为数据源一对多关联的从表字段下载文件。
*
* @param datasourceVariableName 数据源名称。
* @param datasourceId 数据源Id。
* @param relationId 数据源的一对多关联Id。
* @param dataId 附件所在记录的主键Id。
* @param fieldName 数据表字段名。
* @param asImage 是否为图片文件。
* @param response Http 应答对象。
*/
@GetMapping("/downloadOneToManyRelation/{datasourceVariableName}")
public void downloadOneToManyRelation(
@PathVariable("datasourceVariableName") String datasourceVariableName,
@RequestParam Long datasourceId,
@RequestParam Long relationId,
@RequestParam(required = false) String dataId,
@RequestParam String fieldName,
@RequestParam String filename,
@RequestParam Boolean asImage,
HttpServletResponse response) throws Exception {
String errorMessage;
OnlineDatasource datasource = onlineDatasourceService.getById(datasourceId);
if (datasource == null) {
errorMessage = "数据验证失败数据源Id并不存在";
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage));
return;
}
if (!datasource.getVariableName().equals(datasourceVariableName)) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
ResponseResult.error(ErrorCodeEnum.NO_OPERATION_PERMISSION));
return;
}
ResponseResult<OnlineDatasourceRelation> relationResult =
onlineOperationHelper.verifyAndGetOneToManyRelation(datasourceId, relationId);
if (!relationResult.isSuccess()) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN, ResponseResult.errorFrom(relationResult));
return;
}
OnlineTable slaveTable = relationResult.getData().getSlaveTable();
onlineOperationHelper.doDownload(slaveTable, dataId, fieldName, filename, asImage, response);
}
/**
* 为数据源主表字段上传文件。
*
* @param datasourceVariableName 数据源名称。
* @param datasourceId 数据源Id。
* @param fieldName 数据表字段名。
* @param asImage 是否为图片文件。
* @param uploadFile 上传文件对象。
*/
@PostMapping("/uploadDatasource/{datasourceVariableName}")
public void uploadDatasource(
@PathVariable("datasourceVariableName") String datasourceVariableName,
@RequestParam Long datasourceId,
@RequestParam String fieldName,
@RequestParam Boolean asImage,
@RequestParam("uploadFile") MultipartFile uploadFile) throws Exception {
String errorMessage;
ResponseResult<OnlineDatasource> datasourceResult =
onlineOperationHelper.verifyAndGetDatasource(datasourceId);
if (!datasourceResult.isSuccess()) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN, ResponseResult.errorFrom(datasourceResult));
return;
}
OnlineDatasource datasource = datasourceResult.getData();
if (!datasource.getVariableName().equals(datasourceVariableName)) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
ResponseResult.error(ErrorCodeEnum.NO_OPERATION_PERMISSION));
return;
}
OnlineTable masterTable = datasource.getMasterTable();
onlineOperationHelper.doUpload(masterTable, fieldName, asImage, uploadFile);
}
/**
* 为数据源一对多关联的从表字段上传文件。
*
* @param datasourceVariableName 数据源名称。
* @param datasourceId 数据源Id。
* @param relationId 数据源的一对多关联Id。
* @param fieldName 数据表字段名。
* @param asImage 是否为图片文件。
* @param uploadFile 上传文件对象。
*/
@PostMapping("/uploadOneToManyRelation/{datasourceVariableName}")
public void uploadOneToManyRelation(
@PathVariable("datasourceVariableName") String datasourceVariableName,
@RequestParam Long datasourceId,
@RequestParam Long relationId,
@RequestParam String fieldName,
@RequestParam Boolean asImage,
@RequestParam("uploadFile") MultipartFile uploadFile) throws Exception {
String errorMessage;
OnlineDatasource datasource = onlineDatasourceService.getById(datasourceId);
if (datasource == null) {
errorMessage = "数据验证失败数据源Id并不存在";
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage));
return;
}
if (!datasource.getVariableName().equals(datasourceVariableName)) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
ResponseResult.error(ErrorCodeEnum.NO_OPERATION_PERMISSION));
return;
}
ResponseResult<OnlineDatasourceRelation> relationResult =
onlineOperationHelper.verifyAndGetOneToManyRelation(datasourceId, relationId);
if (!relationResult.isSuccess()) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN, ResponseResult.errorFrom(relationResult));
return;
}
OnlineTable slaveTable = relationResult.getData().getSlaveTable();
onlineOperationHelper.doUpload(slaveTable, fieldName, asImage, uploadFile);
}
/**
* 根据数据源Id以及接口参数为动态表单查询数据列表。
*
* @param datasourceVariableName 数据源名称。
* @param datasourceId 数据源Id。
* @param filterDtoList 多虑数据对象列表。
* @param orderParam 排序对象。
* @param pageParam 分页对象。
* @return 查询结果。
*/
@PostMapping("/listByDatasourceId/{datasourceVariableName}")
public ResponseResult<MyPageData<Map<String, Object>>> listByDatasourceId(
@PathVariable("datasourceVariableName") String datasourceVariableName,
@MyRequestBody(required = true) Long datasourceId,
@MyRequestBody(elementType = OnlineFilterDto.class) List<OnlineFilterDto> filterDtoList,
@MyRequestBody MyOrderParam orderParam,
@MyRequestBody MyPageParam pageParam) {
String errorMessage;
// 1. 验证数据源及其关联
ResponseResult<OnlineDatasource> datasourceResult =
onlineOperationHelper.verifyAndGetDatasource(datasourceId);
if (!datasourceResult.isSuccess()) {
return ResponseResult.errorFrom(datasourceResult);
}
OnlineDatasource datasource = datasourceResult.getData();
if (!datasource.getVariableName().equals(datasourceVariableName)) {
ContextUtil.getHttpResponse().setStatus(HttpServletResponse.SC_FORBIDDEN);
return ResponseResult.error(ErrorCodeEnum.NO_OPERATION_PERMISSION);
}
OnlineTable masterTable = datasource.getMasterTable();
ResponseResult<List<OnlineDatasourceRelation>> relationListResult =
onlineOperationHelper.verifyAndGetRelationList(datasourceId, null);
if (!relationListResult.isSuccess()) {
return ResponseResult.errorFrom(relationListResult);
}
List<OnlineDatasourceRelation> allRelationList = relationListResult.getData();
// 2. 验证数据过滤对象中的表名和字段确保没有sql注入。
ResponseResult<Void> filterDtoListResult = this.verifyFilterDtoList(filterDtoList);
if (!filterDtoListResult.isSuccess()) {
return ResponseResult.errorFrom(filterDtoListResult);
}
// 3. 解析排序参数同时确保没有sql注入。
Map<String, OnlineTable> tableMap = new HashMap<>(4);
tableMap.put(masterTable.getTableName(), masterTable);
List<OnlineDatasourceRelation> oneToOneRelationList = relationListResult.getData().stream()
.filter(r -> r.getRelationType().equals(RelationType.ONE_TO_ONE)).collect(Collectors.toList());
if (CollUtil.isNotEmpty(oneToOneRelationList)) {
Map<String, OnlineTable> relationTableMap = oneToOneRelationList.stream()
.map(OnlineDatasourceRelation::getSlaveTable).collect(Collectors.toMap(OnlineTable::getTableName, c -> c));
tableMap.putAll(relationTableMap);
}
ResponseResult<String> orderByResult = this.makeOrderBy(orderParam, masterTable, tableMap);
if (!orderByResult.isSuccess()) {
return ResponseResult.errorFrom(orderByResult);
}
String orderBy = orderByResult.getData();
if (pageParam != null) {
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize());
}
List<Map<String, Object>> resultList = onlineOperationService.getMasterDataList(
masterTable, oneToOneRelationList, allRelationList, filterDtoList, orderBy);
return ResponseResult.success(MyPageUtil.makeResponseData(resultList));
}
/**
* 根据数据源Id和数据源关联Id以及接口参数为动态表单查询该一对多关联的数据列表。
*
* @param datasourceVariableName 数据源名称。
* @param datasourceId 数据源Id。
* @param relationId 数据源的一对多关联Id。
* @param filterDtoList 多虑数据对象列表。
* @param orderParam 排序对象。
* @param pageParam 分页对象。
* @return 查询结果。
*/
@PostMapping("/listByOneToManyRelationId/{datasourceVariableName}")
public ResponseResult<MyPageData<Map<String, Object>>> listByOneToManyRelationId(
@PathVariable("datasourceVariableName") String datasourceVariableName,
@MyRequestBody(required = true) Long datasourceId,
@MyRequestBody(required = true) Long relationId,
@MyRequestBody(elementType = OnlineFilterDto.class) List<OnlineFilterDto> filterDtoList,
@MyRequestBody MyOrderParam orderParam,
@MyRequestBody MyPageParam pageParam) {
String errorMessage;
OnlineDatasource datasource = onlineDatasourceService.getById(datasourceId);
if (datasource == null) {
errorMessage = "数据验证失败数据源Id并不存在";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
if (!datasource.getVariableName().equals(datasourceVariableName)) {
ContextUtil.getHttpResponse().setStatus(HttpServletResponse.SC_FORBIDDEN);
return ResponseResult.error(ErrorCodeEnum.NO_OPERATION_PERMISSION);
}
ResponseResult<OnlineDatasourceRelation> relationResult =
onlineOperationHelper.verifyAndGetOneToManyRelation(datasourceId, relationId);
if (!relationResult.isSuccess()) {
return ResponseResult.errorFrom(relationResult);
}
OnlineDatasourceRelation relation = relationResult.getData();
OnlineTable slaveTable = relation.getSlaveTable();
// 验证数据过滤对象中的表名和字段确保没有sql注入。
ResponseResult<Void> filterDtoListResult = this.verifyFilterDtoList(filterDtoList);
if (!filterDtoListResult.isSuccess()) {
return ResponseResult.errorFrom(filterDtoListResult);
}
Map<String, OnlineTable> tableMap = new HashMap<>(1);
tableMap.put(slaveTable.getTableName(), slaveTable);
if (CollUtil.isNotEmpty(orderParam)) {
for (MyOrderParam.OrderInfo orderInfo : orderParam) {
orderInfo.setFieldName(StrUtil.removePrefix(orderInfo.getFieldName(),
relation.getVariableName() + OnlineConstant.RELATION_TABLE_COLUMN_SEPARATOR));
}
}
ResponseResult<String> orderByResult = this.makeOrderBy(orderParam, slaveTable, tableMap);
if (!orderByResult.isSuccess()) {
return ResponseResult.errorFrom(orderByResult);
}
String orderBy = orderByResult.getData();
// 分页。
if (pageParam != null) {
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize());
}
List<Map<String, Object>> resultList =
onlineOperationService.getSlaveDataList(relation, filterDtoList, orderBy);
return ResponseResult.success(MyPageUtil.makeResponseData(resultList));
}
/**
* 查询字典数据,并以字典的约定方式,返回数据结果集。
*
* @param dictId 字典Id。
* @param filterDtoList 字典的过滤对象列表。
* @return 字典数据列表。
*/
@PostMapping("/listDict")
public ResponseResult<List<Map<String, Object>>> listDict(
@MyRequestBody(required = true) Long dictId,
@MyRequestBody(elementType = OnlineFilterDto.class) List<OnlineFilterDto> filterDtoList) {
String errorMessage;
OnlineDict dict = onlineDictService.getById(dictId);
if (dict == null) {
errorMessage = "数据验证失败字典Id并不存在";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
if (!dict.getDictType().equals(DictType.TABLE)) {
errorMessage = "数据验证失败,该接口仅支持数据表字典!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
if (CollUtil.isNotEmpty(filterDtoList)) {
for (OnlineFilterDto filter : filterDtoList) {
if (!this.checkTableAndColumnName(filter.getColumnName())) {
errorMessage = "数据验证失败,过滤字段名 ["
+ filter.getColumnName() + " ] 包含 (数字、字母和下划线) 之外的非法字符!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
}
}
List<Map<String, Object>> resultList = onlineOperationService.getDictDataList(dict, filterDtoList);
return ResponseResult.success(resultList);
}
private ResponseResult<Void> verifyFilterDtoList(List<OnlineFilterDto> filterDtoList) {
if (CollUtil.isEmpty(filterDtoList)) {
return ResponseResult.success();
}
String errorMessage;
for (OnlineFilterDto filter : filterDtoList) {
if (!this.checkTableAndColumnName(filter.getTableName())) {
errorMessage = "数据验证失败,过滤表名 ["
+ filter.getColumnName() + " ] 包含 (数字、字母和下划线) 之外的非法字符!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
if (!this.checkTableAndColumnName(filter.getColumnName())) {
errorMessage = "数据验证失败,过滤字段名 ["
+ filter.getColumnName() + " ] 包含 (数字、字母和下划线) 之外的非法字符!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
}
return ResponseResult.success();
}
private boolean checkTableAndColumnName(String name) {
if (StrUtil.isBlank(name)) {
return true;
}
for (int i = 0; i < name.length(); i++) {
char c = name.charAt(i);
if (!CharUtil.isLetterOrNumber(c) && !CharUtil.equals('_', c, false)) {
return false;
}
}
return true;
}
private ResponseResult<String> makeOrderBy(
MyOrderParam orderParam, OnlineTable masterTable, Map<String, OnlineTable> tableMap) {
if (CollUtil.isEmpty(orderParam)) {
return ResponseResult.success(null);
}
String errorMessage;
StringBuilder sb = new StringBuilder(128);
for (int i = 0; i < orderParam.size(); i++) {
MyOrderParam.OrderInfo orderInfo = orderParam.get(i);
boolean found = false;
String[] orderArray = StrUtil.splitToArray(orderInfo.getFieldName(), '.');
// 如果没有前缀,我们就可以默认为主表的字段。
if (orderArray.length == 1) {
for (OnlineColumn column : masterTable.getColumnMap().values()) {
if (column.getColumnName().equals(orderArray[0])) {
sb.append(masterTable.getTableName()).append(".").append(column.getColumnName());
if (!orderInfo.getAsc()) {
sb.append(" DESC");
}
if (i != orderParam.size() - 1) {
sb.append(", ");
}
found = true;
break;
}
}
if (!found) {
errorMessage = "数据验证失败,排序字段 ["
+ orderInfo.getFieldName() + "] 在主表 [" + masterTable.getTableName() + "] 中并不存在!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
} else {
String tableName = orderArray[0];
String columnName = orderArray[1];
OnlineTable table = tableMap.get(tableName);
if (table == null) {
errorMessage = "数据验证失败,排序字段 ["
+ orderInfo.getFieldName() + "] 的数据表 [" + tableName + "] 并不属于当前数据源!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
for (OnlineColumn column : table.getColumnMap().values()) {
if (column.getColumnName().equals(columnName)) {
sb.append(tableName).append(".").append(columnName);
if (!orderInfo.getAsc()) {
sb.append(" DESC");
}
if (i != orderParam.size() - 1) {
sb.append(", ");
}
found = true;
break;
}
}
if (!found) {
errorMessage = "数据验证失败,排序字段 ["
+ orderInfo.getFieldName() + "] 在数据表 [" + tableName + "] 中并不存在!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
}
}
return ResponseResult.success(sb.toString());
}
}

View File

@@ -0,0 +1,26 @@
package com.flow.demo.common.online.dao;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.online.model.OnlineColumn;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 字段数据数据操作访问接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineColumnMapper extends BaseDaoMapper<OnlineColumn> {
/**
* 获取过滤后的对象列表。
*
* @param onlineColumnFilter 主表过滤对象。
* @param orderBy 排序字符串order by从句的参数。
* @return 对象列表。
*/
List<OnlineColumn> getOnlineColumnList(
@Param("onlineColumnFilter") OnlineColumn onlineColumnFilter, @Param("orderBy") String orderBy);
}

View File

@@ -0,0 +1,25 @@
package com.flow.demo.common.online.dao;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.online.model.OnlineColumnRule;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Set;
/**
* 数据操作访问接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineColumnRuleMapper extends BaseDaoMapper<OnlineColumnRule> {
/**
* 获取指定字段Id关联的字段规则对象列表同时还关联了每个OnlineRule对象。
*
* @param columnIdSet 字段Id集合。
* @return 关联的字段规则对象列表。
*/
List<OnlineColumnRule> getOnlineColumnRuleListByColumnIds(@Param("columnIdSet") Set<Long> columnIdSet);
}

View File

@@ -0,0 +1,61 @@
package com.flow.demo.common.online.dao;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.online.model.OnlineDatasource;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Set;
/**
* 数据模型数据操作访问接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineDatasourceMapper extends BaseDaoMapper<OnlineDatasource> {
/**
* 获取过滤后的对象列表。
*
* @param onlineDatasourceFilter 主表过滤对象。
* @param orderBy 排序字符串order by从句的参数。
* @return 对象列表。
*/
List<OnlineDatasource> getOnlineDatasourceList(
@Param("onlineDatasourceFilter") OnlineDatasource onlineDatasourceFilter, @Param("orderBy") String orderBy);
/**
* 根据关联主表Id获取关联从表数据列表。
*
* @param pageId 关联主表Id。
* @param onlineDatasourceFilter 从表过滤对象。
* @param orderBy 排序字符串order by从句的参数。
* @return 从表数据列表。
*/
List<OnlineDatasource> getOnlineDatasourceListByPageId(
@Param("pageId") Long pageId,
@Param("onlineDatasourceFilter") OnlineDatasource onlineDatasourceFilter,
@Param("orderBy") String orderBy);
/**
* 根据关联主表Id获取关联从表中没有和主表建立关联关系的数据列表。
*
* @param pageId 关联主表Id。
* @param onlineDatasourceFilter 过滤对象。
* @param orderBy 排序字符串order by从句的参数。
* @return 与主表没有建立关联的从表数据列表。
*/
List<OnlineDatasource> getNotInOnlineDatasourceListByPageId(
@Param("pageId") Long pageId,
@Param("onlineDatasourceFilter") OnlineDatasource onlineDatasourceFilter,
@Param("orderBy") String orderBy);
/**
* 根据在线表单Id集合获取关联的在线数据源对象列表。
*
* @param formIdSet 在线表单Id集合。
* @return 与参数表单Id关联的数据源列表。
*/
List<OnlineDatasource> getOnlineDatasourceListByFormIds(@Param("formIdSet") Set<Long> formIdSet);
}

View File

@@ -0,0 +1,26 @@
package com.flow.demo.common.online.dao;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.online.model.OnlineDatasourceRelation;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 数据关联数据操作访问接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineDatasourceRelationMapper extends BaseDaoMapper<OnlineDatasourceRelation> {
/**
* 获取过滤后的对象列表。
*
* @param filter 主表过滤对象。
* @param orderBy 排序字符串order by从句的参数。
* @return 对象列表。
*/
List<OnlineDatasourceRelation> getOnlineDatasourceRelationList(
@Param("filter") OnlineDatasourceRelation filter, @Param("orderBy") String orderBy);
}

View File

@@ -0,0 +1,13 @@
package com.flow.demo.common.online.dao;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.online.model.OnlineDatasourceTable;
/**
* 数据操作访问接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineDatasourceTableMapper extends BaseDaoMapper<OnlineDatasourceTable> {
}

View File

@@ -0,0 +1,113 @@
package com.flow.demo.common.online.dao;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.online.model.OnlineDblink;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;
/**
* 数据库链接数据操作访问接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineDblinkMapper extends BaseDaoMapper<OnlineDblink> {
/**
* 获取过滤后的对象列表。
*
* @param onlineDblinkFilter 主表过滤对象。
* @param orderBy 排序字符串order by从句的参数。
* @return 对象列表。
*/
List<OnlineDblink> getOnlineDblinkList(
@Param("onlineDblinkFilter") OnlineDblink onlineDblinkFilter, @Param("orderBy") String orderBy);
/**
* 获取当前数据库链接下的所有用于动态表单的表。
*
* @param prefix 动态表单所使用的表的前缀。如果为空,则返回所有数据表。
* @return 所有用于动态表单的表。
*/
@Select("<script>"
+ "SELECT "
+ " table_name tableName, "
+ " table_comment tableComment, "
+ " create_time createTime "
+ "FROM "
+ " information_schema.tables "
+ "WHERE "
+ " table_schema = (SELECT database()) "
+ " <if test=\"prefix != null and prefix != ''\">"
+ " AND table_name like '${prefix}%'"
+ " </if>"
+ "</script>")
List<Map<String, Object>> getTableListWithPrefix(@Param("prefix") String prefix);
/**
* 获取当前数据库链接下指定数据库表的数据。
*
* @param tableName 数据库表名。
* @return 表数据。
*/
@Select("SELECT \n" +
" table_name tableName, \n" +
" table_comment tableComment, \n" +
" create_time createTime \n" +
"FROM \n" +
" information_schema.tables \n" +
"WHERE table_schema = (SELECT database()) AND table_name = #{tableName}")
Map<String, Object> getTableByName(@Param("tableName") String tableName);
/**
* 获取指定表的字段列表。
*
* @param tableName 指定的表名。
* @return 指定表的字段列表。
*/
@Select("SELECT \n" +
" column_name columnName, \n" +
" data_type columnType, \n" +
" column_type fullColumnType, \n" +
" column_comment columnComment, \n" +
" CASE WHEN column_key = 'PRI' THEN 1 ELSE 0 END AS primaryKey, \n" +
" is_nullable nullable, \n" +
" ordinal_position columnShowOrder, \n" +
" extra, \n" +
" CHARACTER_MAXIMUM_LENGTH stringPrecision, \n" +
" numeric_precision numericPrecision, \n" +
" COLUMN_DEFAULT columnDefault \n" +
"FROM information_schema.columns \n" +
"WHERE table_name = #{tableName} \n" +
" AND table_schema = (SELECT database()) ORDER BY ordinal_position")
List<Map<String, Object>> getTableColumnList(@Param("tableName") String tableName);
/**
* 获取指定表的字段对象。
*
* @param tableName 指定的表名。
* @param columnName 指定的字段名。
* @return 指定表的字段。
*/
@Select("SELECT \n" +
" column_name columnName, \n" +
" data_type columnType, \n" +
" column_type fullColumnType, \n" +
" column_comment columnComment, \n" +
" CASE WHEN column_key = 'PRI' THEN 1 ELSE 0 END AS primaryKey, \n" +
" is_nullable nullable, \n" +
" ordinal_position columnShowOrder, \n" +
" extra, \n" +
" CHARACTER_MAXIMUM_LENGTH stringPrecision, \n" +
" numeric_precision numericPrecision, \n" +
" COLUMN_DEFAULT columnDefault \n" +
"FROM information_schema.columns \n" +
"WHERE table_name = #{tableName} \n" +
" AND column_name = #{columnName} \n" +
" AND table_schema = (SELECT database()) ORDER BY ordinal_position")
Map<String, Object> getTableColumnByName(
@Param("tableName") String tableName, @Param("columnName") String columnName);
}

View File

@@ -0,0 +1,26 @@
package com.flow.demo.common.online.dao;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.online.model.OnlineDict;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 在线表单字典数据操作访问接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineDictMapper extends BaseDaoMapper<OnlineDict> {
/**
* 获取过滤后的对象列表。
*
* @param onlineDictFilter 主表过滤对象。
* @param orderBy 排序字符串order by从句的参数。
* @return 对象列表。
*/
List<OnlineDict> getOnlineDictList(
@Param("onlineDictFilter") OnlineDict onlineDictFilter, @Param("orderBy") String orderBy);
}

View File

@@ -0,0 +1,13 @@
package com.flow.demo.common.online.dao;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.online.model.OnlineFormDatasource;
/**
* 在线表单与数据源多对多关联的数据操作访问接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineFormDatasourceMapper extends BaseDaoMapper<OnlineFormDatasource> {
}

View File

@@ -0,0 +1,26 @@
package com.flow.demo.common.online.dao;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.online.model.OnlineForm;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 在线表单数据操作访问接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineFormMapper extends BaseDaoMapper<OnlineForm> {
/**
* 获取过滤后的对象列表。
*
* @param onlineFormFilter 主表过滤对象。
* @param orderBy 排序字符串order by从句的参数。
* @return 对象列表。
*/
List<OnlineForm> getOnlineFormList(
@Param("onlineFormFilter") OnlineForm onlineFormFilter, @Param("orderBy") String orderBy);
}

View File

@@ -0,0 +1,228 @@
package com.flow.demo.common.online.dao;
import com.flow.demo.common.online.dto.OnlineFilterDto;
import com.flow.demo.common.online.object.ColumnData;
import com.flow.demo.common.online.object.JoinTableInfo;
import org.apache.ibatis.annotations.*;
import java.util.List;
import java.util.Map;
/**
* 在线表单运行时数据操作访问接口。
*
* @author Jerry
* @date 2021-06-06
*/
@Mapper
public interface OnlineOperationMapper {
/**
* 插入新数据。
*
* @param tableName 数据表名。
* @param columnNames 字段名列表。
* @param columnValueList 字段值列表。
*/
@Insert("<script>"
+ "INSERT INTO ${tableName} (${columnNames}) VALUES "
+ " <foreach collection=\"columnValueList\" item=\"columnValue\" separator=\",\" open=\"(\" close=\")\">"
+ " #{columnValue} "
+ " </foreach>"
+ "</script>")
void insert(
@Param("tableName") String tableName,
@Param("columnNames") String columnNames,
@Param("columnValueList") List<Object> columnValueList);
/**
* 更新表数据。
*
* @param tableName 数据表名。
* @param updateColumnList 更新字段列表。
* @param whereColumnList 过滤字段列表。
* @param dataPermFilter 数据权限过滤字符串。
* @return 更新行数。
*/
@Update("<script>"
+ "UPDATE ${tableName} SET "
+ " <foreach collection=\"updateColumnList\" item=\"columnData\" separator=\",\" >"
+ " <if test=\"columnData.columnValue != null\">"
+ " ${columnData.column.columnName} = #{columnData.columnValue} "
+ " </if>"
+ " <if test=\"columnData.columnValue == null\">"
+ " ${columnData.column.columnName} = NULL "
+ " </if>"
+ " </foreach>"
+ "<where>"
+ " <foreach collection=\"whereColumnList\" item=\"columnData\" >"
+ " AND ${columnData.column.columnName} = #{columnData.columnValue}"
+ " </foreach>"
+ " <if test=\"dataPermFilter != null and dataPermFilter != ''\">"
+ " AND ${dataPermFilter} "
+ " </if>"
+ "</where>"
+ "</script>")
int update(
@Param("tableName") String tableName,
@Param("updateColumnList") List<ColumnData> updateColumnList,
@Param("whereColumnList") List<ColumnData> whereColumnList,
@Param("dataPermFilter") String dataPermFilter);
/**
* 删除指定数据。
*
* @param tableName 表名。
* @param filterList SQL过滤条件列表。
* @param dataPermFilter 数据权限过滤字符串。
* @return 删除行数。
*/
@Delete("<script>"
+ "DELETE FROM ${tableName} "
+ "<where>"
+ " <if test=\"filterList != null\">"
+ " <foreach collection=\"filterList\" item=\"filter\">"
+ " <if test=\"filter.filterType == 1\">"
+ " AND ${filter.tableName}.${filter.columnName} = #{filter.columnValue} "
+ " </if>"
+ " <if test=\"filter.filterType == 4\">"
+ " AND ${filter.tableName}.${filter.columnName} IN "
+ " <foreach collection=\"filter.columnValueList\" item=\"columnValue\" separator=\",\" open=\"(\" close=\")\">"
+ " #{columnValue} "
+ " </foreach>"
+ " </if>"
+ " </foreach>"
+ " </if>"
+ " <if test=\"dataPermFilter != null and dataPermFilter != ''\">"
+ " AND ${dataPermFilter}"
+ " </if>"
+ "</where>"
+ "</script>")
int delete(
@Param("tableName") String tableName,
@Param("filterList") List<OnlineFilterDto> filterList,
@Param("dataPermFilter") String dataPermFilter);
/**
* 执行动态查询,并返回查询结果集。
*
* @param masterTableName 主表名称。
* @param joinInfoList 关联表信息列表。
* @param selectFields 返回字段列表,逗号分隔。
* @param filterList SQL过滤条件列表。
* @param dataPermFilter 数据权限过滤字符串。
* @param orderBy 排序字符串。
* @return 查询结果集。
*/
@Select("<script>"
+ "SELECT ${selectFields} FROM ${masterTableName} "
+ "<if test=\"joinInfoList != null\">"
+ " <foreach collection=\"joinInfoList\" item=\"joinInfo\">"
+ " <if test=\"joinInfo.leftJoin\">"
+ " LEFT JOIN ${joinInfo.joinTableName} ON ${joinInfo.joinCondition}"
+ " </if>"
+ " <if test=\"!joinInfo.leftJoin\">"
+ " INNER JOIN ${joinInfo.joinTableName} ON ${joinInfo.joinCondition}"
+ " </if>"
+ " </foreach>"
+ "</if>"
+ "<where>"
+ " <if test=\"filterList != null\">"
+ " <foreach collection=\"filterList\" item=\"filter\">"
+ " <if test=\"filter.filterType == 1\">"
+ " AND ${filter.tableName}.${filter.columnName} = #{filter.columnValue} "
+ " </if>"
+ " <if test=\"filter.filterType == 2\">"
+ " AND ${filter.tableName}.${filter.columnName} &gt;= #{filter.columnValueStart} "
+ " AND ${filter.tableName}.${filter.columnName} &lt;= #{filter.columnValueEnd} "
+ " </if>"
+ " <if test=\"filter.filterType == 3\">"
+ " <bind name = \"safeColumnValue\" value = \"'%' + filter.columnValue + '%'\" />"
+ " AND ${filter.tableName}.${filter.columnName} LIKE #{safeColumnValue} "
+ " </if>"
+ " <if test=\"filter.filterType == 4\">"
+ " AND ${filter.tableName}.${filter.columnName} IN "
+ " <foreach collection=\"filter.columnValueList\" item=\"columnValue\" separator=\",\" open=\"(\" close=\")\">"
+ " #{columnValue} "
+ " </foreach>"
+ " </if>"
+ " </foreach>"
+ " </if>"
+ " <if test=\"dataPermFilter != null and dataPermFilter != ''\">"
+ " AND ${dataPermFilter} "
+ " </if>"
+ "</where>"
+ "<if test=\"orderBy != null and orderBy != ''\">"
+ " ORDER BY ${orderBy}"
+ "</if>"
+ "</script>")
List<Map<String, Object>> getList(
@Param("masterTableName") String masterTableName,
@Param("joinInfoList") List<JoinTableInfo> joinInfoList,
@Param("selectFields") String selectFields,
@Param("filterList") List<OnlineFilterDto> filterList,
@Param("dataPermFilter") String dataPermFilter,
@Param("orderBy") String orderBy);
/**
* 以字典键值对的方式返回数据。
*
* @param tableName 表名称。
* @param selectFields 返回字段列表,逗号分隔。
* @param filterList SQL过滤条件列表。
* @param dataPermFilter 数据权限过滤字符串。
* @return 查询结果集。
*/
@Select("<script>"
+ "SELECT ${selectFields} FROM ${tableName} "
+ "<where>"
+ " <if test=\"filterList != null\">"
+ " <foreach collection=\"filterList\" item=\"filter\">"
+ " <if test=\"filter.filterType == 1\">"
+ " AND ${filter.columnName} = #{filter.columnValue} "
+ " </if>"
+ " <if test=\"filter.filterType == 4\">"
+ " AND ${filter.columnName} IN "
+ " <foreach collection=\"filter.columnValueList\" item=\"columnValue\" separator=\",\" open=\"(\" close=\")\">"
+ " #{columnValue} "
+ " </foreach>"
+ " </if>"
+ " </foreach>"
+ " </if>"
+ " <if test=\"dataPermFilter != null and dataPermFilter != ''\">"
+ " AND ${dataPermFilter} "
+ " </if>"
+ "</where>"
+ "</script>")
List<Map<String, Object>> getDictList(
@Param("tableName") String tableName,
@Param("selectFields") String selectFields,
@Param("filterList") List<OnlineFilterDto> filterList,
@Param("dataPermFilter") String dataPermFilter);
/**
* 根据指定的表名、显示字段列表、过滤条件字符串和分组字段,返回聚合计算后的查询结果。
*
* @param selectTable 表名称。
* @param selectFields 返回字段列表,逗号分隔。
* @param whereClause SQL常量形式的条件从句。
* @param groupBy 分组字段列表,逗号分隔。
* @return 对象可选字段Map列表。
*/
@Select("<script>"
+ "SELECT ${selectFields} FROM ${selectTable}"
+ "<where>"
+ " <if test=\"whereClause != null and whereClause != ''\">"
+ " AND ${whereClause}"
+ " </if>"
+ "</where>"
+ "<if test=\"groupBy != null and groupBy != ''\">"
+ " GROUP BY ${groupBy}"
+ "</if>"
+ "</script>")
List<Map<String, Object>> getGroupedListByCondition(
@Param("selectTable") String selectTable,
@Param("selectFields") String selectFields,
@Param("whereClause") String whereClause,
@Param("groupBy") String groupBy);
}

View File

@@ -0,0 +1,13 @@
package com.flow.demo.common.online.dao;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.online.model.OnlinePageDatasource;
/**
* 在线表单页面和数据源关联对象的数据操作访问接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlinePageDatasourceMapper extends BaseDaoMapper<OnlinePageDatasource> {
}

View File

@@ -0,0 +1,35 @@
package com.flow.demo.common.online.dao;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.online.model.OnlinePage;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 在线表单页面数据操作访问接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlinePageMapper extends BaseDaoMapper<OnlinePage> {
/**
* 获取过滤后的对象列表。
*
* @param onlinePageFilter 主表过滤对象。
* @param orderBy 排序字符串order by从句的参数。
* @return 对象列表。
*/
List<OnlinePage> getOnlinePageList(
@Param("onlinePageFilter") OnlinePage onlinePageFilter, @Param("orderBy") String orderBy);
/**
/**
* 根据数据源Id返回使用该数据源的OnlinePage对象。
*
* @param datasourceId 数据源Id。
* @return 使用该数据源的页面列表。
*/
List<OnlinePage> getOnlinePageListByDatasourceId(@Param("datasourceId") Long datasourceId);
}

View File

@@ -0,0 +1,52 @@
package com.flow.demo.common.online.dao;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.online.model.OnlineRule;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 验证规则数据操作访问接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineRuleMapper extends BaseDaoMapper<OnlineRule> {
/**
* 获取过滤后的对象列表。
*
* @param onlineRuleFilter 主表过滤对象。
* @param orderBy 排序字符串order by从句的参数。
* @return 对象列表。
*/
List<OnlineRule> getOnlineRuleList(
@Param("onlineRuleFilter") OnlineRule onlineRuleFilter, @Param("orderBy") String orderBy);
/**
* 根据关联主表Id获取关联从表数据列表。
*
* @param columnId 关联主表Id。
* @param onlineRuleFilter 从表过滤对象。
* @param orderBy 排序字符串order by从句的参数。
* @return 从表数据列表。
*/
List<OnlineRule> getOnlineRuleListByColumnId(
@Param("columnId") Long columnId,
@Param("onlineRuleFilter") OnlineRule onlineRuleFilter,
@Param("orderBy") String orderBy);
/**
* 根据关联主表Id获取关联从表中没有和主表建立关联关系的数据列表。
*
* @param columnId 关联主表Id。
* @param onlineRuleFilter 过滤对象。
* @param orderBy 排序字符串order by从句的参数。
* @return 与主表没有建立关联的从表数据列表。
*/
List<OnlineRule> getNotInOnlineRuleListByColumnId(
@Param("columnId") Long columnId,
@Param("onlineRuleFilter") OnlineRule onlineRuleFilter,
@Param("orderBy") String orderBy);
}

View File

@@ -0,0 +1,34 @@
package com.flow.demo.common.online.dao;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.online.model.OnlineTable;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 数据表数据操作访问接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineTableMapper extends BaseDaoMapper<OnlineTable> {
/**
* 获取过滤后的对象列表。
*
* @param onlineTableFilter 主表过滤对象。
* @param orderBy 排序字符串order by从句的参数。
* @return 对象列表。
*/
List<OnlineTable> getOnlineTableList(
@Param("onlineTableFilter") OnlineTable onlineTableFilter, @Param("orderBy") String orderBy);
/**
* 根据数据源Id获取该数据源及其关联所引用的数据表列表。
*
* @param datasourceId 指定的数据源Id。
* @return 该数据源及其关联所引用的数据表列表。
*/
List<OnlineTable> getOnlineTableListByDatasourceId(@Param("datasourceId") Long datasourceId);
}

View File

@@ -0,0 +1,26 @@
package com.flow.demo.common.online.dao;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.online.model.OnlineVirtualColumn;
import org.apache.ibatis.annotations.Param;
import java.util.*;
/**
* 虚拟字段数据操作访问接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineVirtualColumnMapper extends BaseDaoMapper<OnlineVirtualColumn> {
/**
* 获取过滤后的对象列表。
*
* @param onlineVirtualColumnFilter 主表过滤对象。
* @param orderBy 排序字符串order by从句的参数。
* @return 对象列表。
*/
List<OnlineVirtualColumn> getOnlineVirtualColumnList(
@Param("onlineVirtualColumnFilter") OnlineVirtualColumn onlineVirtualColumnFilter, @Param("orderBy") String orderBy);
}

View File

@@ -0,0 +1,56 @@
<?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="com.flow.demo.common.online.dao.OnlineColumnMapper">
<resultMap id="BaseResultMap" type="com.flow.demo.common.online.model.OnlineColumn">
<id column="column_id" jdbcType="BIGINT" property="columnId"/>
<result column="column_name" jdbcType="VARCHAR" property="columnName"/>
<result column="table_id" jdbcType="BIGINT" property="tableId"/>
<result column="column_type" jdbcType="VARCHAR" property="columnType"/>
<result column="full_column_type" jdbcType="VARCHAR" property="fullColumnType"/>
<result column="primary_key" jdbcType="BIT" property="primaryKey"/>
<result column="auto_increment" jdbcType="BIT" property="autoIncrement"/>
<result column="nullable" jdbcType="BIT" property="nullable"/>
<result column="column_default" jdbcType="VARCHAR" property="columnDefault"/>
<result column="column_show_order" jdbcType="INTEGER" property="columnShowOrder"/>
<result column="column_comment" jdbcType="VARCHAR" property="columnComment"/>
<result column="object_field_name" jdbcType="VARCHAR" property="objectFieldName"/>
<result column="object_field_type" jdbcType="VARCHAR" property="objectFieldType"/>
<result column="filter_type" jdbcType="INTEGER" property="filterType"/>
<result column="parent_key" jdbcType="BIT" property="parentKey"/>
<result column="dept_filter" jdbcType="BIT" property="deptFilter"/>
<result column="user_filter" jdbcType="BIT" property="userFilter"/>
<result column="field_kind" jdbcType="INTEGER" property="fieldKind"/>
<result column="max_file_count" jdbcType="INTEGER" property="maxFileCount"/>
<result column="dict_id" jdbcType="BIGINT" property="dictId"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
</resultMap>
<!-- 如果有逻辑删除字段过滤,请写到这里 -->
<sql id="filterRef">
<!-- 这里必须加上全包名否则当filterRef被其他Mapper.xml包含引用的时候就会调用Mapper.xml中的该SQL片段 -->
<include refid="com.flow.demo.common.online.dao.OnlineColumnMapper.inputFilterRef"/>
</sql>
<!-- 这里仅包含调用接口输入的主表过滤条件 -->
<sql id="inputFilterRef">
<if test="onlineColumnFilter != null">
<if test="onlineColumnFilter.tableId != null">
AND zz_online_column.table_id = #{onlineColumnFilter.tableId}
</if>
<if test="onlineColumnFilter.columnName != null and onlineColumnFilter.columnName != ''">
AND zz_online_column.column_name = #{onlineColumnFilter.columnName}
</if>
</if>
</sql>
<select id="getOnlineColumnList" resultMap="BaseResultMap" parameterType="com.flow.demo.common.online.model.OnlineColumn">
SELECT * FROM zz_online_column
<where>
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
</mapper>

View File

@@ -0,0 +1,30 @@
<?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="com.flow.demo.common.online.dao.OnlineColumnRuleMapper">
<resultMap id="BaseResultMap" type="com.flow.demo.common.online.model.OnlineColumnRule">
<id column="column_id" jdbcType="BIGINT" property="columnId"/>
<id column="rule_id" jdbcType="BIGINT" property="ruleId"/>
<result column="prop_data_json" jdbcType="LONGVARCHAR" property="propDataJson"/>
</resultMap>
<resultMap id="BaseResultMapWithOnlineRule" type="com.flow.demo.common.online.model.OnlineColumnRule" extends="BaseResultMap">
<association property="onlineRule" column="rule_id" foreignColumn="rule_id"
notNullColumn="rule_id" resultMap="com.flow.demo.common.online.dao.OnlineRuleMapper.BaseResultMap" />
</resultMap>
<select id="getOnlineColumnRuleListByColumnIds" resultMap="BaseResultMapWithOnlineRule">
SELECT
zz_online_rule.*,
zz_online_column_rule.*
FROM
zz_online_rule,
zz_online_column_rule
WHERE
zz_online_column_rule.rule_id = zz_online_rule.rule_id
AND zz_online_column_rule.column_id IN
<foreach collection="columnIdSet" item="columnId" separator="," open="(" close=")">
#{columnId}
</foreach>
</select>
</mapper>

View File

@@ -0,0 +1,89 @@
<?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="com.flow.demo.common.online.dao.OnlineDatasourceMapper">
<resultMap id="BaseResultMap" type="com.flow.demo.common.online.model.OnlineDatasource">
<id column="datasource_id" jdbcType="BIGINT" property="datasourceId"/>
<result column="datasource_name" jdbcType="VARCHAR" property="datasourceName"/>
<result column="variable_name" jdbcType="VARCHAR" property="variableName"/>
<result column="dblink_id" jdbcType="BIGINT" property="dblinkId"/>
<result column="master_table_id" jdbcType="BIGINT" property="masterTableId"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
</resultMap>
<resultMap id="BaseResultMapWithOnlinePageDatasource" type="com.flow.demo.common.online.model.OnlineDatasource" extends="BaseResultMap">
<association property="onlinePageDatasource" column="datasource_id" foreignColumn="datasource_id"
notNullColumn="datasource_id" resultMap="com.flow.demo.common.online.dao.OnlinePageDatasourceMapper.BaseResultMap" />
</resultMap>
<!-- 如果有逻辑删除字段过滤,请写到这里 -->
<sql id="filterRef">
<!-- 这里必须加上全包名否则当filterRef被其他Mapper.xml包含引用的时候就会调用Mapper.xml中的该SQL片段 -->
<include refid="com.flow.demo.common.online.dao.OnlineDatasourceMapper.inputFilterRef"/>
</sql>
<!-- 这里仅包含调用接口输入的主表过滤条件 -->
<sql id="inputFilterRef">
<if test="onlineDatasourceFilter != null">
<if test="onlineDatasourceFilter.datasourceName != null and onlineDatasourceFilter.datasourceName != ''">
AND zz_online_datasource.datasource_name = #{onlineDatasourceFilter.datasourceName}
</if>
</if>
</sql>
<select id="getOnlineDatasourceList" resultMap="BaseResultMap" parameterType="com.flow.demo.common.online.model.OnlineDatasource">
SELECT * FROM zz_online_datasource
<where>
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
<select id="getOnlineDatasourceListByPageId" resultMap="BaseResultMapWithOnlinePageDatasource">
SELECT
zz_online_datasource.*,
zz_online_page_datasource.*
FROM
zz_online_datasource,
zz_online_page_datasource
<where>
AND zz_online_page_datasource.page_id = #{pageId}
AND zz_online_page_datasource.datasource_id = zz_online_datasource.datasource_id
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
<select id="getNotInOnlineDatasourceListByPageId" resultMap="BaseResultMap">
SELECT
zz_online_datasource.*
FROM
zz_online_datasource
<where>
AND NOT EXISTS (SELECT * FROM zz_online_page_datasource
WHERE zz_online_page_datasource.page_id = #{pageId} AND zz_online_page_datasource.datasource_id = zz_online_datasource.datasource_id)
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
<select id="getOnlineDatasourceListByFormIds" resultMap="BaseResultMap">
SELECT
zz_online_datasource.*
FROM
zz_online_datasource, zz_online_form_datasource
<where>
AND zz_online_form_datasource.datasource_id = zz_online_datasource.datasource_id
AND zz_online_form_datasource.form_id IN
<foreach collection="formIdSet" item="formId" separator="," open="(" close=")">
#{formId}
</foreach>
</where>
</select>
</mapper>

View File

@@ -0,0 +1,47 @@
<?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="com.flow.demo.common.online.dao.OnlineDatasourceRelationMapper">
<resultMap id="BaseResultMap" type="com.flow.demo.common.online.model.OnlineDatasourceRelation">
<id column="relation_id" jdbcType="BIGINT" property="relationId"/>
<result column="relation_name" jdbcType="VARCHAR" property="relationName"/>
<result column="variable_name" jdbcType="VARCHAR" property="variableName"/>
<result column="datasource_id" jdbcType="BIGINT" property="datasourceId"/>
<result column="relation_type" jdbcType="INTEGER" property="relationType"/>
<result column="master_column_id" jdbcType="BIGINT" property="masterColumnId"/>
<result column="slave_table_id" jdbcType="BIGINT" property="slaveTableId"/>
<result column="slave_column_id" jdbcType="BIGINT" property="slaveColumnId"/>
<result column="cascade_delete" jdbcType="BIT" property="cascadeDelete"/>
<result column="left_join" jdbcType="BIT" property="leftJoin"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
</resultMap>
<!-- 如果有逻辑删除字段过滤,请写到这里 -->
<sql id="filterRef">
<!-- 这里必须加上全包名否则当filterRef被其他Mapper.xml包含引用的时候就会调用Mapper.xml中的该SQL片段 -->
<include refid="com.flow.demo.common.online.dao.OnlineDatasourceRelationMapper.inputFilterRef"/>
</sql>
<!-- 这里仅包含调用接口输入的主表过滤条件 -->
<sql id="inputFilterRef">
<if test="filter != null">
<if test="filter.relationName != null and filter.relationName != ''">
AND zz_online_datasource_relation.relation_name = #{filter.relationName}
</if>
<if test="filter.datasourceId != null">
AND zz_online_datasource_relation.datasource_id = #{filter.datasourceId}
</if>
</if>
</sql>
<select id="getOnlineDatasourceRelationList" resultMap="BaseResultMap"
parameterType="com.flow.demo.common.online.model.OnlineDatasourceRelation">
SELECT * FROM zz_online_datasource_relation
<where>
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
</mapper>

View File

@@ -0,0 +1,10 @@
<?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="com.flow.demo.common.online.dao.OnlineDatasourceTableMapper">
<resultMap id="BaseResultMap" type="com.flow.demo.common.online.model.OnlineDatasourceTable">
<id column="id" jdbcType="BIGINT" property="id"/>
<result column="datasource_id" jdbcType="BIGINT" property="datasourceId"/>
<result column="relation_id" jdbcType="BIGINT" property="relationId"/>
<result column="table_id" jdbcType="BIGINT" property="tableId"/>
</resultMap>
</mapper>

View File

@@ -0,0 +1,34 @@
<?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="com.flow.demo.common.online.dao.OnlineDblinkMapper">
<resultMap id="BaseResultMap" type="com.flow.demo.common.online.model.OnlineDblink">
<id column="dblink_id" jdbcType="BIGINT" property="dblinkId"/>
<result column="dblink_name" jdbcType="VARCHAR" property="dblinkName"/>
<result column="variable_name" jdbcType="VARCHAR" property="variableName"/>
<result column="dblink_desc" jdbcType="VARCHAR" property="dblinkDesc"/>
<result column="dblink_config_constant" jdbcType="INTEGER" property="dblinkConfigConstant"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
</resultMap>
<!-- 如果有逻辑删除字段过滤,请写到这里 -->
<sql id="filterRef">
<!-- 这里必须加上全包名否则当filterRef被其他Mapper.xml包含引用的时候就会调用Mapper.xml中的该SQL片段 -->
<include refid="com.flow.demo.common.online.dao.OnlineDblinkMapper.inputFilterRef"/>
</sql>
<!-- 这里仅包含调用接口输入的主表过滤条件 -->
<sql id="inputFilterRef">
<if test="onlineDblinkFilter != null">
</if>
</sql>
<select id="getOnlineDblinkList" resultMap="BaseResultMap" parameterType="com.flow.demo.common.online.model.OnlineDblink">
SELECT * FROM zz_online_dblink
<where>
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
</mapper>

View File

@@ -0,0 +1,52 @@
<?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="com.flow.demo.common.online.dao.OnlineDictMapper">
<resultMap id="BaseResultMap" type="com.flow.demo.common.online.model.OnlineDict">
<id column="dict_id" jdbcType="BIGINT" property="dictId"/>
<result column="dict_name" jdbcType="VARCHAR" property="dictName"/>
<result column="dict_type" jdbcType="INTEGER" property="dictType"/>
<result column="dblink_id" jdbcType="BIGINT" property="dblinkId"/>
<result column="table_name" jdbcType="VARCHAR" property="tableName"/>
<result column="key_column_name" jdbcType="VARCHAR" property="keyColumnName"/>
<result column="parent_key_column_name" jdbcType="VARCHAR" property="parentKeyColumnName"/>
<result column="value_column_name" jdbcType="VARCHAR" property="valueColumnName"/>
<result column="deleted_column_name" jdbcType="VARCHAR" property="deletedColumnName"/>
<result column="user_filter_column_name" jdbcType="VARCHAR" property="userFilterColumnName"/>
<result column="dept_filter_column_name" jdbcType="VARCHAR" property="deptFilterColumnName"/>
<result column="tenant_filter_column_name" jdbcType="VARCHAR" property="tenantFilterColumnName"/>
<result column="tree_flag" jdbcType="BIT" property="treeFlag"/>
<result column="dict_list_url" jdbcType="VARCHAR" property="dictListUrl"/>
<result column="dict_ids_url" jdbcType="VARCHAR" property="dictIdsUrl"/>
<result column="dict_data_json" jdbcType="LONGVARCHAR" property="dictDataJson"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
</resultMap>
<!-- 如果有逻辑删除字段过滤,请写到这里 -->
<sql id="filterRef">
<!-- 这里必须加上全包名否则当filterRef被其他Mapper.xml包含引用的时候就会调用Mapper.xml中的该SQL片段 -->
<include refid="com.flow.demo.common.online.dao.OnlineDictMapper.inputFilterRef"/>
</sql>
<!-- 这里仅包含调用接口输入的主表过滤条件 -->
<sql id="inputFilterRef">
<if test="onlineDictFilter != null">
<if test="onlineDictFilter.dictName != null and onlineDictFilter.dictName != ''">
AND zz_online_dict.dict_name = #{onlineDictFilter.dictName}
</if>
<if test="onlineDictFilter.dictType != null">
AND zz_online_dict.dict_type = #{onlineDictFilter.dictType}
</if>
</if>
</sql>
<select id="getOnlineDictList" resultMap="BaseResultMap" parameterType="com.flow.demo.common.online.model.OnlineDict">
SELECT * FROM zz_online_dict
<where>
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
</mapper>

View File

@@ -0,0 +1,9 @@
<?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="com.flow.demo.common.online.dao.OnlineFormDatasourceMapper">
<resultMap id="BaseResultMap" type="com.flow.demo.common.online.model.OnlineFormDatasource">
<id column="id" jdbcType="BIGINT" property="id"/>
<result column="form_id" jdbcType="BIGINT" property="formId"/>
<result column="datasource_id" jdbcType="BIGINT" property="datasourceId"/>
</resultMap>
</mapper>

View File

@@ -0,0 +1,51 @@
<?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="com.flow.demo.common.online.dao.OnlineFormMapper">
<resultMap id="BaseResultMap" type="com.flow.demo.common.online.model.OnlineForm">
<id column="form_id" jdbcType="BIGINT" property="formId"/>
<result column="page_id" jdbcType="BIGINT" property="pageId"/>
<result column="form_code" jdbcType="VARCHAR" property="formCode"/>
<result column="form_name" jdbcType="VARCHAR" property="formName"/>
<result column="form_kind" jdbcType="INTEGER" property="formKind"/>
<result column="form_type" jdbcType="INTEGER" property="formType"/>
<result column="master_table_id" jdbcType="BIGINT" property="masterTableId"/>
<result column="widget_json" jdbcType="LONGVARCHAR" property="widgetJson"/>
<result column="params_json" jdbcType="LONGVARCHAR" property="paramsJson"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
</resultMap>
<!-- 如果有逻辑删除字段过滤,请写到这里 -->
<sql id="filterRef">
<!-- 这里必须加上全包名否则当filterRef被其他Mapper.xml包含引用的时候就会调用Mapper.xml中的该SQL片段 -->
<include refid="com.flow.demo.common.online.dao.OnlineFormMapper.inputFilterRef"/>
</sql>
<!-- 这里仅包含调用接口输入的主表过滤条件 -->
<sql id="inputFilterRef">
<if test="onlineFormFilter != null">
<if test="onlineFormFilter.pageId != null">
AND zz_online_form.page_id = #{onlineFormFilter.pageId}
</if>
<if test="onlineFormFilter.formCode != null and onlineFormFilter.formCode != ''">
AND zz_online_form.form_code = #{onlineFormFilter.formCode}
</if>
<if test="onlineFormFilter.formName != null and onlineFormFilter.formName != ''">
AND zz_online_form.form_name = #{onlineFormFilter.formName}
</if>
<if test="onlineFormFilter.formType != null">
AND zz_online_form.form_type = #{onlineFormFilter.formType}
</if>
</if>
</sql>
<select id="getOnlineFormList" resultMap="BaseResultMap" parameterType="com.flow.demo.common.online.model.OnlineForm">
SELECT * FROM zz_online_form
<where>
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
</mapper>

View File

@@ -0,0 +1,9 @@
<?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="com.flow.demo.common.online.dao.OnlinePageDatasourceMapper">
<resultMap id="BaseResultMap" type="com.flow.demo.common.online.model.OnlinePageDatasource">
<id column="id" jdbcType="BIGINT" property="id"/>
<result column="page_id" jdbcType="BIGINT" property="pageId"/>
<result column="datasource_id" jdbcType="BIGINT" property="datasourceId"/>
</resultMap>
</mapper>

View File

@@ -0,0 +1,50 @@
<?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="com.flow.demo.common.online.dao.OnlinePageMapper">
<resultMap id="BaseResultMap" type="com.flow.demo.common.online.model.OnlinePage">
<id column="page_id" jdbcType="BIGINT" property="pageId"/>
<result column="page_code" jdbcType="VARCHAR" property="pageCode"/>
<result column="page_name" jdbcType="VARCHAR" property="pageName"/>
<result column="page_type" jdbcType="INTEGER" property="pageType"/>
<result column="status" jdbcType="INTEGER" property="status"/>
<result column="published" jdbcType="BIT" property="published"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
</resultMap>
<!-- 如果有逻辑删除字段过滤,请写到这里 -->
<sql id="filterRef">
<!-- 这里必须加上全包名否则当filterRef被其他Mapper.xml包含引用的时候就会调用Mapper.xml中的该SQL片段 -->
<include refid="com.flow.demo.common.online.dao.OnlinePageMapper.inputFilterRef"/>
</sql>
<!-- 这里仅包含调用接口输入的主表过滤条件 -->
<sql id="inputFilterRef">
<if test="onlinePageFilter != null">
<if test="onlinePageFilter.pageCode != null and onlinePageFilter.pageCode != ''">
AND zz_online_page.page_code = #{onlinePageFilter.pageCode}
</if>
<if test="onlinePageFilter.pageName != null and onlinePageFilter.pageName != ''">
AND zz_online_page.page_name = #{onlinePageFilter.pageName}
</if>
<if test="onlinePageFilter.pageType != null">
AND zz_online_page.page_type = #{onlinePageFilter.pageType}
</if>
</if>
</sql>
<select id="getOnlinePageList" resultMap="BaseResultMap" parameterType="com.flow.demo.common.online.model.OnlinePage">
SELECT * FROM zz_online_page
<where>
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
<select id="getOnlinePageListByDatasourceId" resultMap="BaseResultMap">
SELECT a.* FROM zz_online_page a, zz_online_page_datasource b
WHERE b.datasource_id = #{datasourceI} AND b.page_id = a.page_id
</select>
</mapper>

View File

@@ -0,0 +1,66 @@
<?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="com.flow.demo.common.online.dao.OnlineRuleMapper">
<resultMap id="BaseResultMap" type="com.flow.demo.common.online.model.OnlineRule">
<id column="rule_id" jdbcType="BIGINT" property="ruleId"/>
<result column="rule_name" jdbcType="VARCHAR" property="ruleName"/>
<result column="rule_type" jdbcType="INTEGER" property="ruleType"/>
<result column="builtin" jdbcType="BIT" property="builtin"/>
<result column="pattern" jdbcType="VARCHAR" property="pattern"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="deleted_flag" jdbcType="INTEGER" property="deletedFlag"/>
</resultMap>
<resultMap id="BaseResultMapWithOnlineColumnRule" type="com.flow.demo.common.online.model.OnlineRule" extends="BaseResultMap">
<association property="onlineColumnRule" column="rule_id" foreignColumn="rule_id"
notNullColumn="rule_id" resultMap="com.flow.demo.common.online.dao.OnlineColumnRuleMapper.BaseResultMap" />
</resultMap>
<!-- 如果有逻辑删除字段过滤,请写到这里 -->
<sql id="filterRef">
AND zz_online_rule.deleted_flag = ${@com.flow.demo.common.core.constant.GlobalDeletedFlag@NORMAL}
</sql>
<select id="getOnlineRuleList" resultMap="BaseResultMap" parameterType="com.flow.demo.common.online.model.OnlineRule">
SELECT * FROM zz_online_rule
<where>
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
<select id="getOnlineRuleListByColumnId" resultMap="BaseResultMapWithOnlineColumnRule">
SELECT
zz_online_rule.*,
zz_online_column_rule.*
FROM
zz_online_rule,
zz_online_column_rule
<where>
AND zz_online_column_rule.column_id = #{columnId}
AND zz_online_column_rule.rule_id = zz_online_rule.rule_id
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
<select id="getNotInOnlineRuleListByColumnId" resultMap="BaseResultMap">
SELECT
zz_online_rule.*
FROM
zz_online_rule
<where>
AND NOT EXISTS (SELECT * FROM zz_online_column_rule
WHERE zz_online_column_rule.column_id = #{columnId} AND zz_online_column_rule.rule_id = zz_online_rule.rule_id)
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
</mapper>

View File

@@ -0,0 +1,48 @@
<?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="com.flow.demo.common.online.dao.OnlineTableMapper">
<resultMap id="BaseResultMap" type="com.flow.demo.common.online.model.OnlineTable">
<id column="table_id" jdbcType="BIGINT" property="tableId"/>
<result column="table_name" jdbcType="VARCHAR" property="tableName"/>
<result column="model_name" jdbcType="VARCHAR" property="modelName"/>
<result column="dblink_id" jdbcType="BIGINT" property="dblinkId"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
</resultMap>
<!-- 如果有逻辑删除字段过滤,请写到这里 -->
<sql id="filterRef">
<!-- 这里必须加上全包名否则当filterRef被其他Mapper.xml包含引用的时候就会调用Mapper.xml中的该SQL片段 -->
<include refid="com.flow.demo.common.online.dao.OnlineTableMapper.inputFilterRef"/>
</sql>
<!-- 这里仅包含调用接口输入的主表过滤条件 -->
<sql id="inputFilterRef">
<if test="onlineTableFilter != null">
<if test="onlineTableFilter.tableName != null and onlineTableFilter.tableName != ''">
AND zz_online_table.table_name = #{onlineTableFilter.tableName}
</if>
<if test="onlineTableFilter.modelName != null and onlineTableFilter.modelName != ''">
AND zz_online_table.model_name = #{onlineTableFilter.modelName}
</if>
<if test="onlineTableFilter.dblinkId != null">
AND zz_online_table.dblink_id = #{onlineTableFilter.dblinkId}
</if>
</if>
</sql>
<select id="getOnlineTableList" resultMap="BaseResultMap" parameterType="com.flow.demo.common.online.model.OnlineTable">
SELECT * FROM zz_online_table
<where>
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
<select id="getOnlineTableListByDatasourceId" resultMap="BaseResultMap">
SELECT a.* FROM zz_online_table a, zz_online_datasource_table b
WHERE b.datasource_id = #{datasourceId} AND b.table_id = a.table_id
</select>
</mapper>

View File

@@ -0,0 +1,56 @@
<?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="com.flow.demo.common.online.dao.OnlineVirtualColumnMapper">
<resultMap id="BaseResultMap" type="com.flow.demo.common.online.model.OnlineVirtualColumn">
<id column="virtual_column_id" jdbcType="BIGINT" property="virtualColumnId"/>
<result column="table_id" jdbcType="BIGINT" property="tableId"/>
<result column="object_field_name" jdbcType="VARCHAR" property="objectFieldName"/>
<result column="object_field_type" jdbcType="VARCHAR" property="objectFieldType"/>
<result column="column_prompt" jdbcType="VARCHAR" property="columnPrompt"/>
<result column="virtual_type" jdbcType="INTEGER" property="virtualType"/>
<result column="datasource_id" jdbcType="BIGINT" property="datasourceId"/>
<result column="relation_id" jdbcType="BIGINT" property="relationId"/>
<result column="aggregation_table_id" jdbcType="BIGINT" property="aggregationTableId"/>
<result column="aggregation_column_id" jdbcType="BIGINT" property="aggregationColumnId"/>
<result column="aggregation_type" jdbcType="INTEGER" property="aggregationType"/>
<result column="where_clause_json" jdbcType="VARCHAR" property="whereClauseJson"/>
</resultMap>
<!-- 如果有逻辑删除字段过滤,请写到这里 -->
<sql id="filterRef">
<!-- 这里必须加上全包名否则当filterRef被其他Mapper.xml包含引用的时候就会调用Mapper.xml中的该SQL片段 -->
<include refid="com.flow.demo.common.online.dao.OnlineVirtualColumnMapper.inputFilterRef"/>
</sql>
<!-- 这里仅包含调用接口输入的主表过滤条件 -->
<sql id="inputFilterRef">
<if test="onlineVirtualColumnFilter != null">
<if test="onlineVirtualColumnFilter.datasourceId != null">
AND zz_online_virtual_column.datasource_id = #{onlineVirtualColumnFilter.datasourceId}
</if>
<if test="onlineVirtualColumnFilter.relationId != null">
AND zz_online_virtual_column.relation_id = #{onlineVirtualColumnFilter.relationId}
</if>
<if test="onlineVirtualColumnFilter.tableId != null">
AND zz_online_virtual_column.table_id = #{onlineVirtualColumnFilter.tableId}
</if>
<if test="onlineVirtualColumnFilter.aggregationColumnId != null">
AND zz_online_virtual_column.aggregation_column_id = #{onlineVirtualColumnFilter.aggregationColumnId}
</if>
<if test="onlineVirtualColumnFilter.virtualType != null">
AND zz_online_virtual_column.virtual_type = #{onlineVirtualColumnFilter.virtualType}
</if>
</if>
</sql>
<select id="getOnlineVirtualColumnList" resultMap="BaseResultMap"
parameterType="com.flow.demo.common.online.model.OnlineVirtualColumn">
SELECT * FROM zz_online_virtual_column
<where>
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
</mapper>

View File

@@ -0,0 +1,137 @@
package com.flow.demo.common.online.dto;
import com.flow.demo.common.core.validator.ConstDictRef;
import com.flow.demo.common.core.validator.UpdateGroup;
import com.flow.demo.common.online.model.constant.FieldFilterType;
import com.flow.demo.common.online.model.constant.FieldKind;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 在线表单数据表字段Dto对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
public class OnlineColumnDto {
/**
* 主键Id。
*/
@NotNull(message = "数据验证失败主键Id不能为空", groups = {UpdateGroup.class})
private Long columnId;
/**
* 字段名。
*/
@NotBlank(message = "数据验证失败,字段名不能为空!")
private String columnName;
/**
* 数据表Id。
*/
@NotNull(message = "数据验证失败数据表Id不能为空")
private Long tableId;
/**
* 数据表中的字段类型。
*/
@NotBlank(message = "数据验证失败,数据表中的字段类型不能为空!")
private String columnType;
/**
* 数据表中的完整字段类型(包括了精度和刻度)。
*/
@NotBlank(message = "数据验证失败,数据表中的完整字段类型(包括了精度和刻度)不能为空!")
private String fullColumnType;
/**
* 是否为主键。
*/
@NotNull(message = "数据验证失败,是否为主键不能为空!")
private Boolean primaryKey;
/**
* 是否是自增主键(0: 不是 1: 是)。
*/
@NotNull(message = "数据验证失败,是否是自增主键(0: 不是 1: 是)不能为空!")
private Boolean autoIncrement;
/**
* 是否可以为空 (0: 不可以为空 1: 可以为空)。
*/
@NotNull(message = "数据验证失败,是否可以为空 (0: 不可以为空 1: 可以为空)不能为空!")
private Boolean nullable;
/**
* 缺省值。
*/
private String columnDefault;
/**
* 字段在数据表中的显示位置。
*/
@NotNull(message = "数据验证失败,字段在数据表中的显示位置不能为空!")
private Integer columnShowOrder;
/**
* 数据表中的字段注释。
*/
private String columnComment;
/**
* 对象映射字段名称。
*/
@NotBlank(message = "数据验证失败,对象映射字段名称不能为空!")
private String objectFieldName;
/**
* 对象映射字段类型。
*/
@NotBlank(message = "数据验证失败,对象映射字段类型不能为空!")
private String objectFieldType;
/**
* 过滤类型字段。
*/
@NotNull(message = "数据验证失败,过滤类型字段不能为空!", groups = {UpdateGroup.class})
@ConstDictRef(constDictClass = FieldFilterType.class, message = "数据验证失败,过滤类型字段为无效值!")
private Integer filterType;
/**
* 是否是主键的父Id。
*/
@NotNull(message = "数据验证失败是否是主键的父Id不能为空")
private Boolean parentKey;
/**
* 是否部门过滤字段。
*/
@NotNull(message = "数据验证失败,是否部门过滤字段标记不能为空!")
private Boolean deptFilter;
/**
* 是否用户过滤字段。
*/
@NotNull(message = "数据验证失败,是否用户过滤字段标记不能为空!")
private Boolean userFilter;
/**
* 字段类别。
*/
@ConstDictRef(constDictClass = FieldKind.class, message = "数据验证失败,字段类别为无效值!")
private Integer fieldKind;
/**
* 包含的文件文件数量0表示无限制。
*/
private Integer maxFileCount;
/**
* 字典Id。
*/
private Long dictId;
}

View File

@@ -0,0 +1,33 @@
package com.flow.demo.common.online.dto;
import com.flow.demo.common.core.validator.UpdateGroup;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 在线表单数据表字段规则和字段多对多关联Dto对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
public class OnlineColumnRuleDto {
/**
* 字段Id。
*/
@NotNull(message = "数据验证失败字段Id不能为空", groups = {UpdateGroup.class})
private Long columnId;
/**
* 规则Id。
*/
@NotNull(message = "数据验证失败规则Id不能为空", groups = {UpdateGroup.class})
private Long ruleId;
/**
* 规则属性数据。
*/
private String propDataJson;
}

View File

@@ -0,0 +1,54 @@
package com.flow.demo.common.online.dto;
import com.flow.demo.common.core.validator.AddGroup;
import com.flow.demo.common.core.validator.UpdateGroup;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 在线表单的数据源Dto对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
public class OnlineDatasourceDto {
/**
* 主键Id。
*/
@NotNull(message = "数据验证失败主键Id不能为空", groups = {UpdateGroup.class})
private Long datasourceId;
/**
* 数据源名称。
*/
@NotBlank(message = "数据验证失败,数据源名称不能为空!")
private String datasourceName;
/**
* 数据源变量名会成为数据访问url的一部分。
*/
@NotBlank(message = "数据验证失败,数据源变量名不能为空!")
private String variableName;
/**
* 主表所在的数据库链接Id。
*/
@NotNull(message = "数据验证失败数据库链接Id不能为空")
private Long dblinkId;
/**
* 主表Id。
*/
@NotNull(message = "数据验证失败主表Id不能为空", groups = {UpdateGroup.class})
private Long masterTableId;
/**
* 主表表名。
*/
@NotBlank(message = "数据验证失败,主表名不能为空!", groups = {AddGroup.class})
private String masterTableName;
}

View File

@@ -0,0 +1,93 @@
package com.flow.demo.common.online.dto;
import com.flow.demo.common.core.validator.AddGroup;
import com.flow.demo.common.core.validator.ConstDictRef;
import com.flow.demo.common.core.validator.UpdateGroup;
import com.flow.demo.common.online.model.constant.RelationType;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 在线表单的数据源关联Dto对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
public class OnlineDatasourceRelationDto {
/**
* 主键Id。
*/
@NotNull(message = "数据验证失败主键Id不能为空", groups = {UpdateGroup.class})
private Long relationId;
/**
* 关联名称。
*/
@NotBlank(message = "数据验证失败,关联名称不能为空!")
private String relationName;
/**
* 变量名。
*/
@NotBlank(message = "数据验证失败,变量名不能为空!")
private String variableName;
/**
* 主数据源Id。
*/
@NotNull(message = "数据验证失败主数据源Id不能为空")
private Long datasourceId;
/**
* 关联类型。
*/
@NotNull(message = "数据验证失败,关联类型不能为空!")
@ConstDictRef(constDictClass = RelationType.class, message = "数据验证失败,关联类型为无效值!")
private Integer relationType;
/**
* 主表关联字段Id。
*/
@NotNull(message = "数据验证失败主表关联字段Id不能为空")
private Long masterColumnId;
/**
* 从表Id。
*/
@NotNull(message = "数据验证失败从表Id不能为空", groups = {UpdateGroup.class})
private Long slaveTableId;
/**
* 从表名。
*/
@NotBlank(message = "数据验证失败,从表名不能为空!", groups = {AddGroup.class})
private String slaveTableName;
/**
* 从表关联字段Id。
*/
@NotNull(message = "数据验证失败从表关联字段Id不能为空", groups = {UpdateGroup.class})
private Long slaveColumnId;
/**
* 从表字段名。
*/
@NotBlank(message = "数据验证失败,从表字段名不能为空!", groups = {AddGroup.class})
private String slaveColumnName;
/**
* 是否级联删除标记。
*/
@NotNull(message = "数据验证失败,是否级联删除标记不能为空!")
private Boolean cascadeDelete;
/**
* 是否左连接标记。
*/
@NotNull(message = "数据验证失败,是否左连接标记不能为空!")
private Boolean leftJoin;
}

View File

@@ -0,0 +1,46 @@
package com.flow.demo.common.online.dto;
import com.flow.demo.common.core.validator.UpdateGroup;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 在线表单数据表所在数据库链接Dto对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
public class OnlineDblinkDto {
/**
* 主键Id。
*/
@NotNull(message = "数据验证失败主键Id不能为空", groups = {UpdateGroup.class})
private Long dblinkId;
/**
* 链接中文名称。
*/
@NotBlank(message = "数据验证失败,链接中文名称不能为空!")
private String dblinkName;
/**
* 链接英文名称。
*/
@NotBlank(message = "数据验证失败,链接英文名称不能为空!")
private String variableName;
/**
* 链接描述。
*/
private String dblinkDesc;
/**
* 数据源配置常量。
*/
@NotNull(message = "数据验证失败,数据源配置常量不能为空!")
private Integer dblinkConfigConstant;
}

View File

@@ -0,0 +1,104 @@
package com.flow.demo.common.online.dto;
import com.flow.demo.common.core.validator.ConstDictRef;
import com.flow.demo.common.core.validator.UpdateGroup;
import com.flow.demo.common.online.model.constant.DictType;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 在线表单关联的字典Dto对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
public class OnlineDictDto {
/**
* 主键Id。
*/
@NotNull(message = "数据验证失败主键Id不能为空", groups = {UpdateGroup.class})
private Long dictId;
/**
* 字典名称。
*/
@NotBlank(message = "数据验证失败,字典名称不能为空!")
private String dictName;
/**
* 字典类型。
*/
@NotNull(message = "数据验证失败,字典类型不能为空!")
@ConstDictRef(constDictClass = DictType.class, message = "数据验证失败,字典类型为无效值!")
private Integer dictType;
/**
* 数据库链接Id。
*/
private Long dblinkId;
/**
* 字典表名称。
*/
private String tableName;
/**
* 字典表键字段名称。
*/
private String keyColumnName;
/**
* 字典表父键字段名称。
*/
private String parentKeyColumnName;
/**
* 字典值字段名称。
*/
private String valueColumnName;
/**
* 逻辑删除字段。
*/
private String deletedColumnName;
/**
* 用户过滤滤字段名称。
*/
private String userFilterColumnName;
/**
* 部门过滤字段名称。
*/
private String deptFilterColumnName;
/**
* 租户过滤字段名称。
*/
private String tenantFilterColumnName;
/**
* 是否树形标记。
*/
@NotNull(message = "数据验证失败,是否树形标记不能为空!")
private Boolean treeFlag;
/**
* 获取字典数据的url。
*/
private String dictListUrl;
/**
* 根据主键id批量获取字典数据的url。
*/
private String dictIdsUrl;
/**
* 字典的JSON数据。
*/
private String dictDataJson;
}

View File

@@ -0,0 +1,51 @@
package com.flow.demo.common.online.dto;
import com.flow.demo.common.online.model.constant.FieldFilterType;
import lombok.Data;
import java.util.Set;
/**
* 在线表单数据过滤参数对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
public class OnlineFilterDto {
/**
* 表名。
*/
private String tableName;
/**
* 过滤字段名。
*/
private String columnName;
/**
* 过滤值。
*/
private Object columnValue;
/**
* 范围比较的最小值。
*/
private Object columnValueStart;
/**
* 范围比较的最大值。
*/
private Object columnValueEnd;
/**
* 仅当操作符为IN的时候使用。
*/
private Set<Object> columnValueList;
/**
* 过滤类型参考FieldFilterType常量对象。缺省值就是等于过滤了。
*/
private Integer filterType = FieldFilterType.EQUAL_FILTER;
}

View File

@@ -0,0 +1,79 @@
package com.flow.demo.common.online.dto;
import com.flow.demo.common.core.validator.ConstDictRef;
import com.flow.demo.common.core.validator.UpdateGroup;
import com.flow.demo.common.online.model.constant.FormKind;
import com.flow.demo.common.online.model.constant.FormType;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 在线表单Dto对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
public class OnlineFormDto {
/**
* 主键Id。
*/
@NotNull(message = "数据验证失败主键Id不能为空", groups = {UpdateGroup.class})
private Long formId;
/**
* 页面id。
*/
@NotNull(message = "数据验证失败页面id不能为空")
private Long pageId;
/**
* 表单编码。
*/
private String formCode;
/**
* 表单名称。
*/
@NotBlank(message = "数据验证失败,表单名称不能为空!")
private String formName;
/**
* 表单类别。
*/
@NotNull(message = "数据验证失败,表单类别不能为空!")
@ConstDictRef(constDictClass = FormKind.class, message = "数据验证失败,表单类别为无效值!")
private Integer formKind;
/**
* 表单类型。
*/
@NotNull(message = "数据验证失败,表单类型不能为空!")
@ConstDictRef(constDictClass = FormType.class, message = "数据验证失败,表单类型为无效值!")
private Integer formType;
/**
* 表单主表id。
*/
@NotNull(message = "数据验证失败表单主表id不能为空")
private Long masterTableId;
/**
* 当前表单关联的数据源Id集合。
*/
private List<Long> datasourceIdList;
/**
* 表单组件JSON。
*/
private String widgetJson;
/**
* 表单参数JSON。
*/
private String paramsJson;
}

View File

@@ -0,0 +1,34 @@
package com.flow.demo.common.online.dto;
import com.flow.demo.common.core.validator.UpdateGroup;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 在线表单页面和数据源多对多关联Dto对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
public class OnlinePageDatasourceDto {
/**
* 主键Id。
*/
@NotNull(message = "数据验证失败主键Id不能为空", groups = {UpdateGroup.class})
private Long id;
/**
* 页面主键Id。
*/
@NotNull(message = "数据验证失败页面主键Id不能为空")
private Long pageId;
/**
* 数据源主键Id。
*/
@NotNull(message = "数据验证失败数据源主键Id不能为空")
private Long datasourceId;
}

View File

@@ -0,0 +1,51 @@
package com.flow.demo.common.online.dto;
import com.flow.demo.common.core.validator.ConstDictRef;
import com.flow.demo.common.core.validator.UpdateGroup;
import com.flow.demo.common.online.model.constant.PageStatus;
import com.flow.demo.common.online.model.constant.PageType;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 在线表单所在页面Dto对象。这里我们可以把页面理解为表单的容器。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
public class OnlinePageDto {
/**
* 主键Id。
*/
@NotNull(message = "数据验证失败主键Id不能为空", groups = {UpdateGroup.class})
private Long pageId;
/**
* 页面编码。
*/
private String pageCode;
/**
* 页面名称。
*/
@NotBlank(message = "数据验证失败,页面名称不能为空!")
private String pageName;
/**
* 页面类型。
*/
@NotNull(message = "数据验证失败,页面类型不能为空!")
@ConstDictRef(constDictClass = PageType.class, message = "数据验证失败,页面类型为无效值!")
private Integer pageType;
/**
* 页面编辑状态。
*/
@NotNull(message = "数据验证失败,状态不能为空!")
@ConstDictRef(constDictClass = PageStatus.class, message = "数据验证失败,状态为无效值!")
private Integer status;
}

View File

@@ -0,0 +1,49 @@
package com.flow.demo.common.online.dto;
import com.flow.demo.common.core.validator.ConstDictRef;
import com.flow.demo.common.core.validator.UpdateGroup;
import com.flow.demo.common.online.model.constant.RuleType;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 在线表单数据表字段验证规则Dto对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
public class OnlineRuleDto {
/**
* 主键Id。
*/
@NotNull(message = "数据验证失败主键Id不能为空", groups = {UpdateGroup.class})
private Long ruleId;
/**
* 规则名称。
*/
@NotBlank(message = "数据验证失败,规则名称不能为空!")
private String ruleName;
/**
* 规则类型。
*/
@NotNull(message = "数据验证失败,规则类型不能为空!")
@ConstDictRef(constDictClass = RuleType.class, message = "数据验证失败,规则类型为无效值!")
private Integer ruleType;
/**
* 内置规则标记。
*/
@NotNull(message = "数据验证失败,内置规则标记不能为空!")
private Boolean builtin;
/**
* 自定义规则的正则表达式。
*/
private String pattern;
}

View File

@@ -0,0 +1,41 @@
package com.flow.demo.common.online.dto;
import com.flow.demo.common.core.validator.UpdateGroup;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 在线表单的数据表Dto对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
public class OnlineTableDto {
/**
* 主键Id。
*/
@NotNull(message = "数据验证失败主键Id不能为空", groups = {UpdateGroup.class})
private Long tableId;
/**
* 表名称。
*/
@NotBlank(message = "数据验证失败,表名称不能为空!")
private String tableName;
/**
* 实体名称。
*/
@NotBlank(message = "数据验证失败,实体名称不能为空!")
private String modelName;
/**
* 数据库链接Id。
*/
@NotNull(message = "数据验证失败数据库链接Id不能为空")
private Long dblinkId;
}

View File

@@ -0,0 +1,88 @@
package com.flow.demo.common.online.dto;
import com.flow.demo.common.core.constant.AggregationType;
import com.flow.demo.common.core.validator.ConstDictRef;
import com.flow.demo.common.core.validator.UpdateGroup;
import com.flow.demo.common.online.model.constant.VirtualType;
import lombok.Data;
import javax.validation.constraints.*;
/**
* 在线数据表虚拟字段Dto对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
public class OnlineVirtualColumnDto {
/**
* 主键Id。
*/
@NotNull(message = "数据验证失败主键Id不能为空", groups = {UpdateGroup.class})
private Long virtualColumnId;
/**
* 所在表Id。
*/
private Long tableId;
/**
* 字段名称。
*/
@NotBlank(message = "数据验证失败,字段名称不能为空!")
private String objectFieldName;
/**
* 属性类型。
*/
@NotBlank(message = "数据验证失败,属性类型不能为空!")
private String objectFieldType;
/**
* 字段提示名。
*/
@NotBlank(message = "数据验证失败,字段提示名不能为空!")
private String columnPrompt;
/**
* 虚拟字段类型(0: 聚合)。
*/
@ConstDictRef(constDictClass = VirtualType.class, message = "数据验证失败,虚拟字段类型为无效值!")
@NotNull(message = "数据验证失败,虚拟字段类型(0: 聚合)不能为空!")
private Integer virtualType;
/**
* 关联数据源Id。
*/
@NotNull(message = "数据验证失败关联数据源Id不能为空")
private Long datasourceId;
/**
* 关联Id。
*/
private Long relationId;
/**
* 聚合字段所在关联表Id。
*/
private Long aggregationTableId;
/**
* 关联表聚合字段Id。
*/
private Long aggregationColumnId;
/**
* 聚合类型(0: sum 1: count 2: avg 3: min 4: max)。
*/
@ConstDictRef(constDictClass = AggregationType.class, message = "数据验证失败,虚拟字段聚合计算类型为无效值!")
private Integer aggregationType;
/**
* 存储过滤条件的json。
*/
private String whereClauseJson;
}

View File

@@ -0,0 +1,196 @@
package com.flow.demo.common.online.model;
import com.baomidou.mybatisplus.annotation.*;
import com.flow.demo.common.core.annotation.RelationConstDict;
import com.flow.demo.common.core.annotation.RelationOneToOne;
import com.flow.demo.common.core.base.mapper.BaseModelMapper;
import com.flow.demo.common.online.model.constant.FieldKind;
import com.flow.demo.common.online.vo.OnlineColumnVo;
import lombok.Data;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import java.util.Date;
import java.util.Map;
/**
* 在线表单数据表字段实体对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
@TableName(value = "zz_online_column")
public class OnlineColumn {
/**
* 主键Id。
*/
@TableId(value = "column_id")
private Long columnId;
/**
* 字段名。
*/
@TableField(value = "column_name")
private String columnName;
/**
* 数据表Id。
*/
@TableField(value = "table_id")
private Long tableId;
/**
* 数据表中的字段类型。
*/
@TableField(value = "column_type")
private String columnType;
/**
* 数据表中的完整字段类型(包括了精度和刻度)。
*/
@TableField(value = "full_column_type")
private String fullColumnType;
/**
* 是否为主键。
*/
@TableField(value = "primary_key")
private Boolean primaryKey;
/**
* 是否是自增主键(0: 不是 1: 是)。
*/
@TableField(value = "auto_increment")
private Boolean autoIncrement;
/**
* 是否可以为空 (0: 不可以为空 1: 可以为空)。
*/
@TableField(value = "nullable")
private Boolean nullable;
/**
* 缺省值。
*/
@TableField(value = "column_default")
private String columnDefault;
/**
* 字段在数据表中的显示位置。
*/
@TableField(value = "column_show_order")
private Integer columnShowOrder;
/**
* 数据表中的字段注释。
*/
@TableField(value = "column_comment")
private String columnComment;
/**
* 对象映射字段名称。
*/
@TableField(value = "object_field_name")
private String objectFieldName;
/**
* 对象映射字段类型。
*/
@TableField(value = "object_field_type")
private String objectFieldType;
/**
* 过滤字段类型。
*/
@TableField(value = "filter_type")
private Integer filterType;
/**
* 是否是主键的父Id。
*/
@TableField(value = "parent_key")
private Boolean parentKey;
/**
* 是否部门过滤字段。
*/
@TableField(value = "dept_filter")
private Boolean deptFilter;
/**
* 是否用户过滤字段。
*/
@TableField(value = "user_filter")
private Boolean userFilter;
/**
* 字段类别。
*/
@TableField(value = "field_kind")
private Integer fieldKind;
/**
* 包含的文件文件数量0表示无限制。
*/
@TableField(value = "max_file_count")
private Integer maxFileCount;
/**
* 字典Id。
*/
@TableField(value = "dict_id")
private Long dictId;
/**
* 更新时间。
*/
@TableField(value = "update_time")
private Date updateTime;
/**
* 创建时间。
*/
@TableField(value = "create_time")
private Date createTime;
@RelationConstDict(
masterIdField = "fieldKind",
constantDictClass = FieldKind.class)
@TableField(exist = false)
private Map<String, Object> fieldKindDictMap;
@RelationOneToOne(
masterIdField = "dictId",
slaveServiceName = "OnlineDictService",
slaveIdField = "dictId",
slaveModelClass = OnlineDict.class,
loadSlaveDict = false)
@TableField(exist = false)
private OnlineDict dictInfo;
@Mapper
public interface OnlineColumnModelMapper extends BaseModelMapper<OnlineColumnVo, OnlineColumn> {
/**
* 转换Vo对象到实体对象。
*
* @param onlineColumnVo 域对象。
* @return 实体对象。
*/
@Mapping(target = "dictInfo", expression = "java(mapToBean(onlineColumnVo.getDictInfo(), com.flow.demo.common.online.model.OnlineDict.class))")
@Override
OnlineColumn toModel(OnlineColumnVo onlineColumnVo);
/**
* 转换实体对象到VO对象。
*
* @param onlineColumn 实体对象。
* @return 域对象。
*/
@Mapping(target = "dictInfo", expression = "java(beanToMap(onlineColumn.getDictInfo(), false))")
@Override
OnlineColumnVo fromModel(OnlineColumn onlineColumn);
}
public static final OnlineColumnModelMapper INSTANCE = Mappers.getMapper(OnlineColumnModelMapper.class);
}

View File

@@ -0,0 +1,36 @@
package com.flow.demo.common.online.model;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
/**
* 在线表单数据表字段规则和字段多对多关联实体对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
@TableName(value = "zz_online_column_rule")
public class OnlineColumnRule {
/**
* 字段Id。
*/
@TableField(value = "column_id")
private Long columnId;
/**
* 规则Id。
*/
@TableField(value = "rule_id")
private Long ruleId;
/**
* 规则属性数据。
*/
@TableField(value = "prop_data_json")
private String propDataJson;
@TableField(exist = false)
private OnlineRule onlineRule;
}

View File

@@ -0,0 +1,107 @@
package com.flow.demo.common.online.model;
import com.baomidou.mybatisplus.annotation.*;
import com.flow.demo.common.core.annotation.RelationDict;
import com.flow.demo.common.core.base.mapper.BaseModelMapper;
import com.flow.demo.common.online.vo.OnlineDatasourceVo;
import lombok.Data;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import java.util.Date;
import java.util.Map;
/**
* 在线表单的数据源实体对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
@TableName(value = "zz_online_datasource")
public class OnlineDatasource {
/**
* 主键Id。
*/
@TableId(value = "datasource_id")
private Long datasourceId;
/**
* 数据源名称。
*/
@TableField(value = "datasource_name")
private String datasourceName;
/**
* 数据源变量名会成为数据访问url的一部分。
*/
@TableField(value = "variable_name")
private String variableName;
/**
* 数据库链接Id。
*/
@TableField(value = "dblink_id")
private Long dblinkId;
/**
* 主表Id。
*/
@TableField(value = "master_table_id")
private Long masterTableId;
/**
* 更新时间。
*/
@TableField(value = "update_time")
private Date updateTime;
/**
* 创建时间。
*/
@TableField(value = "create_time")
private Date createTime;
/**
* datasourceId 的多对多关联表数据对象。
*/
@TableField(exist = false)
private OnlinePageDatasource onlinePageDatasource;
@RelationDict(
masterIdField = "masterTableId",
slaveServiceName = "onlineTableService",
slaveModelClass = OnlineTable.class,
slaveIdField = "tableId",
slaveNameField = "tableName")
@TableField(exist = false)
private Map<String, Object> masterTableIdDictMap;
@TableField(exist = false)
private OnlineTable masterTable;
@Mapper
public interface OnlineDatasourceModelMapper extends BaseModelMapper<OnlineDatasourceVo, OnlineDatasource> {
/**
* 转换Vo对象到实体对象。
*
* @param onlineDatasourceVo 域对象。
* @return 实体对象。
*/
@Mapping(target = "onlinePageDatasource", expression = "java(mapToBean(onlineDatasourceVo.getOnlinePageDatasource(), com.flow.demo.common.online.model.OnlinePageDatasource.class))")
@Override
OnlineDatasource toModel(OnlineDatasourceVo onlineDatasourceVo);
/**
* 转换实体对象到VO对象。
*
* @param onlineDatasource 实体对象。
* @return 域对象。
*/
@Mapping(target = "onlinePageDatasource", expression = "java(beanToMap(onlineDatasource.getOnlinePageDatasource(), false))")
@Override
OnlineDatasourceVo fromModel(OnlineDatasource onlineDatasource);
}
public static final OnlineDatasourceModelMapper INSTANCE = Mappers.getMapper(OnlineDatasourceModelMapper.class);
}

View File

@@ -0,0 +1,187 @@
package com.flow.demo.common.online.model;
import com.baomidou.mybatisplus.annotation.*;
import com.flow.demo.common.core.annotation.RelationConstDict;
import com.flow.demo.common.core.annotation.RelationDict;
import com.flow.demo.common.core.annotation.RelationOneToOne;
import com.flow.demo.common.core.base.mapper.BaseModelMapper;
import com.flow.demo.common.online.model.constant.RelationType;
import com.flow.demo.common.online.vo.OnlineDatasourceRelationVo;
import lombok.Data;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import java.util.Date;
import java.util.Map;
/**
* 在线表单的数据源关联实体对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
@TableName(value = "zz_online_datasource_relation")
public class OnlineDatasourceRelation {
/**
* 主键Id。
*/
@TableId(value = "relation_id")
private Long relationId;
/**
* 关联名称。
*/
@TableField(value = "relation_name")
private String relationName;
/**
* 变量名。
*/
@TableField(value = "variable_name")
private String variableName;
/**
* 主数据源Id。
*/
@TableField(value = "datasource_id")
private Long datasourceId;
/**
* 关联类型。
*/
@TableField(value = "relation_type")
private Integer relationType;
/**
* 主表关联字段Id。
*/
@TableField(value = "master_column_id")
private Long masterColumnId;
/**
* 从表Id。
*/
@TableField(value = "slave_table_id")
private Long slaveTableId;
/**
* 从表关联字段Id。
*/
@TableField(value = "slave_column_id")
private Long slaveColumnId;
/**
* 删除主表的时候是否级联删除一对一和一对多的从表数据,多对多只是删除关联,不受到这个标记的影响。。
*/
@TableField(value = "cascade_delete")
private Boolean cascadeDelete;
/**
* 是否左连接。
*/
@TableField(value = "left_join")
private Boolean leftJoin;
/**
* 更新时间。
*/
@TableField(value = "update_time")
private Date updateTime;
/**
* 创建时间。
*/
@TableField(value = "create_time")
private Date createTime;
@RelationOneToOne(
masterIdField = "masterColumnId",
slaveServiceName = "onlineColumnService",
slaveModelClass = OnlineColumn.class,
slaveIdField = "columnId")
@TableField(exist = false)
private OnlineColumn masterColumn;
@RelationOneToOne(
masterIdField = "slaveTableId",
slaveServiceName = "onlineTableService",
slaveModelClass = OnlineTable.class,
slaveIdField = "tableId")
@TableField(exist = false)
private OnlineTable slaveTable;
@RelationOneToOne(
masterIdField = "slaveColumnId",
slaveServiceName = "onlineColumnService",
slaveModelClass = OnlineColumn.class,
slaveIdField = "columnId")
@TableField(exist = false)
private OnlineColumn slaveColumn;
@RelationDict(
masterIdField = "masterColumnId",
slaveServiceName = "onlineColumnService",
equalOneToOneRelationField = "onlineColumn",
slaveModelClass = OnlineColumn.class,
slaveIdField = "columnId",
slaveNameField = "columnName")
@TableField(exist = false)
private Map<String, Object> masterColumnIdDictMap;
@RelationDict(
masterIdField = "slaveTableId",
slaveServiceName = "onlineTableService",
equalOneToOneRelationField = "onlineTable",
slaveModelClass = OnlineTable.class,
slaveIdField = "tableId",
slaveNameField = "modelName")
@TableField(exist = false)
private Map<String, Object> slaveTableIdDictMap;
@RelationDict(
masterIdField = "slaveColumnId",
slaveServiceName = "onlineColumnService",
equalOneToOneRelationField = "onlineColumn",
slaveModelClass = OnlineColumn.class,
slaveIdField = "columnId",
slaveNameField = "columnName")
@TableField(exist = false)
private Map<String, Object> slaveColumnIdDictMap;
@RelationConstDict(
masterIdField = "relationType",
constantDictClass = RelationType.class)
@TableField(exist = false)
private Map<String, Object> relationTypeDictMap;
@Mapper
public interface OnlineDatasourceRelationModelMapper
extends BaseModelMapper<OnlineDatasourceRelationVo, OnlineDatasourceRelation> {
/**
* 转换Vo对象到实体对象。
*
* @param onlineDatasourceRelationVo 域对象。
* @return 实体对象。
*/
@Mapping(target = "masterColumn", expression = "java(mapToBean(onlineDatasourceRelationVo.getMasterColumn(), com.flow.demo.common.online.model.OnlineColumn.class))")
@Mapping(target = "slaveTable", expression = "java(mapToBean(onlineDatasourceRelationVo.getSlaveTable(), com.flow.demo.common.online.model.OnlineTable.class))")
@Mapping(target = "slaveColumn", expression = "java(mapToBean(onlineDatasourceRelationVo.getSlaveColumn(), com.flow.demo.common.online.model.OnlineColumn.class))")
@Override
OnlineDatasourceRelation toModel(OnlineDatasourceRelationVo onlineDatasourceRelationVo);
/**
* 转换实体对象到VO对象。
*
* @param onlineDatasourceRelation 实体对象。
* @return 域对象。
*/
@Mapping(target = "masterColumn", expression = "java(beanToMap(onlineDatasourceRelation.getMasterColumn(), false))")
@Mapping(target = "slaveTable", expression = "java(beanToMap(onlineDatasourceRelation.getSlaveTable(), false))")
@Mapping(target = "slaveColumn", expression = "java(beanToMap(onlineDatasourceRelation.getSlaveColumn(), false))")
@Override
OnlineDatasourceRelationVo fromModel(OnlineDatasourceRelation onlineDatasourceRelation);
}
public static final OnlineDatasourceRelationModelMapper INSTANCE = Mappers.getMapper(OnlineDatasourceRelationModelMapper.class);
}

View File

@@ -0,0 +1,39 @@
package com.flow.demo.common.online.model;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
/**
* 数据源及其关联所引用的数据表实体对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
@TableName(value = "zz_online_datasource_table")
public class OnlineDatasourceTable {
/**
* 主键Id。
*/
@TableId(value = "id")
private Long id;
/**
* 数据源Id。
*/
@TableField(value = "datasource_id")
private Long datasourceId;
/**
* 数据源关联Id。
*/
@TableField(value = "relation_id")
private Long relationId;
/**
* 数据表Id。
*/
@TableField(value = "table_id")
private Long tableId;
}

View File

@@ -0,0 +1,62 @@
package com.flow.demo.common.online.model;
import com.baomidou.mybatisplus.annotation.*;
import com.flow.demo.common.core.base.mapper.BaseModelMapper;
import com.flow.demo.common.online.vo.OnlineDblinkVo;
import lombok.Data;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.Date;
/**
* 在线表单数据表所在数据库链接实体对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
@TableName(value = "zz_online_dblink")
public class OnlineDblink {
/**
* 主键Id。
*/
@TableId(value = "dblink_id")
private Long dblinkId;
/**
* 链接中文名称。
*/
@TableField(value = "dblink_name")
private String dblinkName;
/**
* 链接英文名称。
*/
@TableField(value = "variable_name")
private String variableName;
/**
* 链接描述。
*/
@TableField(value = "dblink_desc")
private String dblinkDesc;
/**
* 数据源配置常量。
*/
@TableField(value = "dblink_config_constant")
private Integer dblinkConfigConstant;
/**
* 创建时间。
*/
@TableField(value = "create_time")
private Date createTime;
@Mapper
public interface OnlineDblinkModelMapper extends BaseModelMapper<OnlineDblinkVo, OnlineDblink> {
}
public static final OnlineDblinkModelMapper INSTANCE = Mappers.getMapper(OnlineDblinkModelMapper.class);
}

View File

@@ -0,0 +1,169 @@
package com.flow.demo.common.online.model;
import com.baomidou.mybatisplus.annotation.*;
import com.flow.demo.common.core.annotation.RelationConstDict;
import com.flow.demo.common.core.annotation.RelationDict;
import com.flow.demo.common.core.base.mapper.BaseModelMapper;
import com.flow.demo.common.online.model.constant.DictType;
import com.flow.demo.common.online.vo.OnlineDictVo;
import lombok.Data;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.Date;
import java.util.Map;
/**
* 在线表单关联的字典实体对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
@TableName(value = "zz_online_dict")
public class OnlineDict {
/**
* 主键Id。
*/
@TableId(value = "dict_id")
private Long dictId;
/**
* 字典名称。
*/
@TableField(value = "dict_name")
private String dictName;
/**
* 字典类型。
*/
@TableField(value = "dict_type")
private Integer dictType;
/**
* 数据库链接Id。
*/
@TableField(value = "dblink_id")
private Long dblinkId;
/**
* 字典表名称。
*/
@TableField(value = "table_name")
private String tableName;
/**
* 字典表键字段名称。
*/
@TableField(value = "key_column_name")
private String keyColumnName;
/**
* 字典表父键字段名称。
*/
@TableField(value = "parent_key_column_name")
private String parentKeyColumnName;
/**
* 字典值字段名称。
*/
@TableField(value = "value_column_name")
private String valueColumnName;
/**
* 逻辑删除字段。
*/
@TableField(value = "deleted_column_name")
private String deletedColumnName;
/**
* 用户过滤滤字段名称。
*/
@TableField(value = "user_filter_column_name")
private String userFilterColumnName;
/**
* 部门过滤字段名称。
*/
@TableField(value = "dept_filter_column_name")
private String deptFilterColumnName;
/**
* 租户过滤字段名称。
*/
@TableField(value = "tenant_filter_column_name")
private String tenantFilterColumnName;
/**
* 是否树形标记。
*/
@TableField(value = "tree_flag")
private Boolean treeFlag;
/**
* 获取字典数据的url。
*/
@TableField(value = "dict_list_url")
private String dictListUrl;
/**
* 根据主键id批量获取字典数据的url。
*/
@TableField(value = "dict_ids_url")
private String dictIdsUrl;
/**
* 字典的JSON数据。
*/
@TableField(value = "dict_data_json")
private String dictDataJson;
/**
* 更新时间。
*/
@TableField(value = "update_time")
private Date updateTime;
/**
* 创建时间。
*/
@TableField(value = "create_time")
private Date createTime;
@RelationConstDict(
masterIdField = "dictType",
constantDictClass = DictType.class)
@TableField(exist = false)
private Map<String, Object> dictTypeDictMap;
@RelationDict(
masterIdField = "dblinkId",
slaveServiceName = "onlineDblinkService",
slaveModelClass = OnlineDblink.class,
slaveIdField = "dblinkId",
slaveNameField = "dblinkName")
@TableField(exist = false)
private Map<String, Object> dblinkIdDictMap;
@Mapper
public interface OnlineDictModelMapper extends BaseModelMapper<OnlineDictVo, OnlineDict> {
/**
* 转换Vo对象到实体对象。
*
* @param onlineDictVo 域对象。
* @return 实体对象。
*/
@Override
OnlineDict toModel(OnlineDictVo onlineDictVo);
/**
* 转换实体对象到VO对象。
*
* @param onlineDict 实体对象。
* @return 域对象。
*/
@Override
OnlineDictVo fromModel(OnlineDict onlineDict);
}
public static final OnlineDictModelMapper INSTANCE = Mappers.getMapper(OnlineDictModelMapper.class);
}

View File

@@ -0,0 +1,138 @@
package com.flow.demo.common.online.model;
import com.baomidou.mybatisplus.annotation.*;
import com.flow.demo.common.core.annotation.*;
import com.flow.demo.common.core.base.mapper.BaseModelMapper;
import com.flow.demo.common.online.model.constant.FormType;
import com.flow.demo.common.online.vo.OnlineFormVo;
import lombok.Data;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import java.util.Date;
import java.util.Map;
/**
* 在线表单实体对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
@TableName(value = "zz_online_form")
public class OnlineForm {
/**
* 主键Id。
*/
@TableId(value = "form_id")
private Long formId;
/**
* 页面id。
*/
@TableField(value = "page_id")
private Long pageId;
/**
* 表单编码。
*/
@TableField(value = "form_code")
private String formCode;
/**
* 表单名称。
*/
@TableField(value = "form_name")
private String formName;
/**
* 表单类别。
*/
@TableField(value = "form_kind")
private Integer formKind;
/**
* 表单类型。
*/
@TableField(value = "form_type")
private Integer formType;
/**
* 表单主表id。
*/
@TableField(value = "master_table_id")
private Long masterTableId;
/**
* 表单组件JSON。
*/
@TableField(value = "widget_json")
private String widgetJson;
/**
* 表单参数JSON。
*/
@TableField(value = "params_json")
private String paramsJson;
/**
* 更新时间。
*/
@TableField(value = "update_time")
private Date updateTime;
/**
* 创建时间。
*/
@TableField(value = "create_time")
private Date createTime;
@RelationOneToOne(
masterIdField = "masterTableId",
slaveServiceName = "onlineTableService",
slaveModelClass = OnlineTable.class,
slaveIdField = "tableId")
@TableField(exist = false)
private OnlineTable onlineTable;
@RelationDict(
masterIdField = "masterTableId",
slaveServiceName = "onlineTableService",
equalOneToOneRelationField = "onlineTable",
slaveModelClass = OnlineTable.class,
slaveIdField = "tableId",
slaveNameField = "modelName")
@TableField(exist = false)
private Map<String, Object> masterTableIdDictMap;
@RelationConstDict(
masterIdField = "formType",
constantDictClass = FormType.class)
@TableField(exist = false)
private Map<String, Object> formTypeDictMap;
@Mapper
public interface OnlineFormModelMapper extends BaseModelMapper<OnlineFormVo, OnlineForm> {
/**
* 转换Vo对象到实体对象。
*
* @param onlineFormVo 域对象。
* @return 实体对象。
*/
@Mapping(target = "onlineTable", expression = "java(mapToBean(onlineFormVo.getOnlineTable(), com.flow.demo.common.online.model.OnlineTable.class))")
@Override
OnlineForm toModel(OnlineFormVo onlineFormVo);
/**
* 转换实体对象到VO对象。
*
* @param onlineForm 实体对象。
* @return 域对象。
*/
@Mapping(target = "onlineTable", expression = "java(beanToMap(onlineForm.getOnlineTable(), false))")
@Override
OnlineFormVo fromModel(OnlineForm onlineForm);
}
public static final OnlineFormModelMapper INSTANCE = Mappers.getMapper(OnlineFormModelMapper.class);
}

View File

@@ -0,0 +1,33 @@
package com.flow.demo.common.online.model;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
/**
* 在线表单和数据源多对多关联实体对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
@TableName(value = "zz_online_form_datasource")
public class OnlineFormDatasource {
/**
* 主键Id。
*/
@TableId(value = "id")
private Long id;
/**
* 表单Id。
*/
@TableField(value = "form_id")
private Long formId;
/**
* 数据源Id。
*/
@TableField(value = "datasource_id")
private Long datasourceId;
}

View File

@@ -0,0 +1,106 @@
package com.flow.demo.common.online.model;
import com.baomidou.mybatisplus.annotation.*;
import com.flow.demo.common.core.annotation.RelationConstDict;
import com.flow.demo.common.core.base.mapper.BaseModelMapper;
import com.flow.demo.common.online.model.constant.PageStatus;
import com.flow.demo.common.online.model.constant.PageType;
import com.flow.demo.common.online.vo.OnlinePageVo;
import lombok.Data;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.Date;
import java.util.Map;
/**
* 在线表单所在页面实体对象。这里我们可以把页面理解为表单的容器。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
@TableName(value = "zz_online_page")
public class OnlinePage {
/**
* 主键Id。
*/
@TableId(value = "page_id")
private Long pageId;
/**
* 页面编码。
*/
@TableField(value = "page_code")
private String pageCode;
/**
* 页面名称。
*/
@TableField(value = "page_name")
private String pageName;
/**
* 页面类型。
*/
@TableField(value = "page_type")
private Integer pageType;
/**
* 页面编辑状态。
*/
@TableField(value = "status")
private Integer status;
/**
* 是否发布。
*/
@TableField(value = "published")
private Boolean published;
/**
* 更新时间。
*/
@TableField(value = "update_time")
private Date updateTime;
/**
* 创建时间。
*/
@TableField(value = "create_time")
private Date createTime;
@RelationConstDict(
masterIdField = "pageType",
constantDictClass = PageType.class)
@TableField(exist = false)
private Map<String, Object> pageTypeDictMap;
@RelationConstDict(
masterIdField = "status",
constantDictClass = PageStatus.class)
@TableField(exist = false)
private Map<String, Object> statusDictMap;
@Mapper
public interface OnlinePageModelMapper extends BaseModelMapper<OnlinePageVo, OnlinePage> {
/**
* 转换Vo对象到实体对象。
*
* @param onlinePageVo 域对象。
* @return 实体对象。
*/
@Override
OnlinePage toModel(OnlinePageVo onlinePageVo);
/**
* 转换实体对象到VO对象。
*
* @param onlinePage 实体对象。
* @return 域对象。
*/
@Override
OnlinePageVo fromModel(OnlinePage onlinePage);
}
public static final OnlinePageModelMapper INSTANCE = Mappers.getMapper(OnlinePageModelMapper.class);
}

View File

@@ -0,0 +1,33 @@
package com.flow.demo.common.online.model;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
/**
* 在线表单页面和数据源多对多关联实体对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
@TableName(value = "zz_online_page_datasource")
public class OnlinePageDatasource {
/**
* 主键Id。
*/
@TableId(value = "id")
private Long id;
/**
* 页面主键Id。
*/
@TableField(value = "page_id")
private Long pageId;
/**
* 数据源主键Id。
*/
@TableField(value = "datasource_id")
private Long datasourceId;
}

View File

@@ -0,0 +1,109 @@
package com.flow.demo.common.online.model;
import com.baomidou.mybatisplus.annotation.*;
import com.flow.demo.common.core.annotation.RelationConstDict;
import com.flow.demo.common.core.base.mapper.BaseModelMapper;
import com.flow.demo.common.online.model.constant.RuleType;
import com.flow.demo.common.online.vo.OnlineRuleVo;
import lombok.Data;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import java.util.Date;
import java.util.Map;
/**
* 在线表单数据表字段验证规则实体对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
@TableName(value = "zz_online_rule")
public class OnlineRule {
/**
* 主键Id。
*/
@TableId(value = "rule_id")
private Long ruleId;
/**
* 规则名称。
*/
@TableField(value = "rule_name")
private String ruleName;
/**
* 规则类型。
*/
@TableField(value = "rule_type")
private Integer ruleType;
/**
* 内置规则标记。
*/
@TableField(value = "builtin")
private Boolean builtin;
/**
* 自定义规则的正则表达式。
*/
@TableField(value = "pattern")
private String pattern;
/**
* 更新时间。
*/
@TableField(value = "update_time")
private Date updateTime;
/**
* 创建时间。
*/
@TableField(value = "create_time")
private Date createTime;
/**
* 逻辑删除标记字段(1: 正常 -1: 已删除)。
*/
@TableLogic
@TableField(value = "deleted_flag")
private Integer deletedFlag;
/**
* ruleId 的多对多关联表数据对象。
*/
@TableField(exist = false)
private OnlineColumnRule onlineColumnRule;
@RelationConstDict(
masterIdField = "ruleType",
constantDictClass = RuleType.class)
@TableField(exist = false)
private Map<String, Object> ruleTypeDictMap;
@Mapper
public interface OnlineRuleModelMapper extends BaseModelMapper<OnlineRuleVo, OnlineRule> {
/**
* 转换Vo对象到实体对象。
*
* @param onlineRuleVo 域对象。
* @return 实体对象。
*/
@Mapping(target = "onlineColumnRule", expression = "java(mapToBean(onlineRuleVo.getOnlineColumnRule(), com.flow.demo.common.online.model.OnlineColumnRule.class))")
@Override
OnlineRule toModel(OnlineRuleVo onlineRuleVo);
/**
* 转换实体对象到VO对象。
*
* @param onlineRule 实体对象。
* @return 域对象。
*/
@Mapping(target = "onlineColumnRule", expression = "java(beanToMap(onlineRule.getOnlineColumnRule(), false))")
@Override
OnlineRuleVo fromModel(OnlineRule onlineRule);
}
public static final OnlineRuleModelMapper INSTANCE = Mappers.getMapper(OnlineRuleModelMapper.class);
}

View File

@@ -0,0 +1,107 @@
package com.flow.demo.common.online.model;
import com.baomidou.mybatisplus.annotation.*;
import com.flow.demo.common.core.annotation.RelationOneToMany;
import com.flow.demo.common.core.base.mapper.BaseModelMapper;
import com.flow.demo.common.online.vo.OnlineTableVo;
import lombok.Data;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 在线表单的数据表实体对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
@TableName(value = "zz_online_table")
public class OnlineTable {
/**
* 主键Id。
*/
@TableId(value = "table_id")
private Long tableId;
/**
* 表名称。
*/
@TableField(value = "table_name")
private String tableName;
/**
* 实体名称。
*/
@TableField(value = "model_name")
private String modelName;
/**
* 数据库链接Id。
*/
@TableField(value = "dblink_id")
private Long dblinkId;
/**
* 更新时间。
*/
@TableField(value = "update_time")
private Date updateTime;
/**
* 创建时间。
*/
@TableField(value = "create_time")
private Date createTime;
@RelationOneToMany(
masterIdField = "tableId",
slaveServiceName = "onlineColumnService",
slaveModelClass = OnlineColumn.class,
slaveIdField = "tableId")
@TableField(exist = false)
private List<OnlineColumn> columnList;
/**
* 该字段会被缓存因此在线表单执行操作时可以从缓存中读取该数据并可基于columnId进行快速检索。
*/
@TableField(exist = false)
private Map<Long, OnlineColumn> columnMap;
/**
* 当前表的主键字段该字段仅仅用于动态表单运行时的SQL拼装。
*/
@TableField(exist = false)
private OnlineColumn primaryKeyColumn;
/**
* 当前表的逻辑删除字段该字段仅仅用于动态表单运行时的SQL拼装。
*/
@TableField(exist = false)
private OnlineColumn logicDeleteColumn;
@Mapper
public interface OnlineTableModelMapper extends BaseModelMapper<OnlineTableVo, OnlineTable> {
/**
* 转换Vo对象到实体对象。
*
* @param onlineTableVo 域对象。
* @return 实体对象。
*/
@Override
OnlineTable toModel(OnlineTableVo onlineTableVo);
/**
* 转换实体对象到VO对象。
*
* @param onlineTable 实体对象。
* @return 域对象。
*/
@Override
OnlineTableVo fromModel(OnlineTable onlineTable);
}
public static final OnlineTableModelMapper INSTANCE = Mappers.getMapper(OnlineTableModelMapper.class);
}

View File

@@ -0,0 +1,96 @@
package com.flow.demo.common.online.model;
import com.baomidou.mybatisplus.annotation.*;
import com.flow.demo.common.core.base.mapper.BaseModelMapper;
import com.flow.demo.common.online.vo.OnlineVirtualColumnVo;
import lombok.Data;
import org.mapstruct.*;
import org.mapstruct.factory.Mappers;
/**
* 在线数据表虚拟字段实体对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
@TableName(value = "zz_online_virtual_column")
public class OnlineVirtualColumn {
/**
* 主键Id。
*/
@TableId(value = "virtual_column_id")
private Long virtualColumnId;
/**
* 所在表Id。
*/
@TableField(value = "table_id")
private Long tableId;
/**
* 字段名称。
*/
@TableField(value = "object_field_name")
private String objectFieldName;
/**
* 属性类型。
*/
@TableField(value = "object_field_type")
private String objectFieldType;
/**
* 字段提示名。
*/
@TableField(value = "column_prompt")
private String columnPrompt;
/**
* 虚拟字段类型(0: 聚合)。
*/
@TableField(value = "virtual_type")
private Integer virtualType;
/**
* 关联数据源Id。
*/
@TableField(value = "datasource_id")
private Long datasourceId;
/**
* 关联Id。
*/
@TableField(value = "relation_id")
private Long relationId;
/**
* 聚合字段所在关联表Id。
*/
@TableField(value = "aggregation_table_id")
private Long aggregationTableId;
/**
* 关联表聚合字段Id。
*/
@TableField(value = "aggregation_column_id")
private Long aggregationColumnId;
/**
* 聚合类型(0: count 1: sum 2: avg 3: max 4:min)。
*/
@TableField(value = "aggregation_type")
private Integer aggregationType;
/**
* 存储过滤条件的json。
*/
@TableField(value = "where_clause_json")
private String whereClauseJson;
@Mapper
public interface OnlineVirtualColumnModelMapper extends BaseModelMapper<OnlineVirtualColumnVo, OnlineVirtualColumn> {
}
public static final OnlineVirtualColumnModelMapper INSTANCE = Mappers.getMapper(OnlineVirtualColumnModelMapper.class);
}

View File

@@ -0,0 +1,54 @@
package com.flow.demo.common.online.model.constant;
import java.util.HashMap;
import java.util.Map;
/**
* 在线表单字典类型常量字典对象。
*
* @author Jerry
* @date 2021-06-06
*/
public final class DictType {
/**
* 数据表字典。
*/
public static final int TABLE = 1;
/**
* URL字典。
*/
public static final int URL = 5;
/**
* 常量字典。
*/
public static final int CONST = 10;
/**
* 自定义字典。
*/
public static final int CUSTOM = 15;
private static final Map<Object, String> DICT_MAP = new HashMap<>(2);
static {
DICT_MAP.put(TABLE, "数据表字典");
DICT_MAP.put(URL, "URL字典");
DICT_MAP.put(CONST, "静态字典");
DICT_MAP.put(CUSTOM, "自定义字典");
}
/**
* 判断参数是否为当前常量字典的合法值。
*
* @param value 待验证的参数值。
* @return 合法返回true否则false。
*/
public static boolean isValid(Integer value) {
return value != null && DICT_MAP.containsKey(value);
}
/**
* 私有构造函数,明确标识该常量类的作用。
*/
private DictType() {
}
}

View File

@@ -0,0 +1,59 @@
package com.flow.demo.common.online.model.constant;
import java.util.HashMap;
import java.util.Map;
/**
* 字段过滤类型常量字典对象。
*
* @author Jerry
* @date 2021-06-06
*/
public final class FieldFilterType {
/**
* 无过滤。
*/
public static final int NO_FILTER = 0;
/**
* 等于过滤。
*/
public static final int EQUAL_FILTER = 1;
/**
* 范围过滤。
*/
public static final int RANGE_FILTER = 2;
/**
* 模糊过滤。
*/
public static final int LIKE_FILTER = 3;
/**
* IN LIST列表过滤。
*/
public static final int IN_LIST_FILTER = 4;
private static final Map<Object, String> DICT_MAP = new HashMap<>(9);
static {
DICT_MAP.put(NO_FILTER, "无过滤");
DICT_MAP.put(EQUAL_FILTER, "等于过滤");
DICT_MAP.put(RANGE_FILTER, "范围过滤");
DICT_MAP.put(LIKE_FILTER, "模糊过滤");
DICT_MAP.put(IN_LIST_FILTER, "IN LIST列表过滤");
}
/**
* 判断参数是否为当前常量字典的合法值。
*
* @param value 待验证的参数值。
* @return 合法返回true否则false。
*/
public static boolean isValid(Integer value) {
return value != null && DICT_MAP.containsKey(value);
}
/**
* 私有构造函数,明确标识该常量类的作用。
*/
private FieldFilterType() {
}
}

View File

@@ -0,0 +1,74 @@
package com.flow.demo.common.online.model.constant;
import java.util.HashMap;
import java.util.Map;
/**
* 字段类别常量字典对象。
*
* @author Jerry
* @date 2021-06-06
*/
public final class FieldKind {
/**
* 文件上传字段。
*/
public static final int UPLOAD = 1;
/**
* 图片上传字段。
*/
public static final int UPLOAD_IMAGE = 2;
/**
* 富文本字段。
*/
public static final int RICH_TEXT = 3;
/**
* 创建时间字段。
*/
public static final int CREATE_TIME = 20;
/**
* 创建人字段。
*/
public static final int CREATE_USER_ID = 21;
/**
* 更新时间字段。
*/
public static final int UPDATE_TIME = 22;
/**
* 更新人字段。
*/
public static final int UPDATE_USER_ID = 23;
/**
* 逻辑删除字段。
*/
public static final int LOGIC_DELETE = 31;
private static final Map<Object, String> DICT_MAP = new HashMap<>(9);
static {
DICT_MAP.put(UPLOAD, "文件上传字段");
DICT_MAP.put(UPLOAD_IMAGE, "图片上传字段");
DICT_MAP.put(RICH_TEXT, "富文本字段");
DICT_MAP.put(CREATE_TIME, "创建时间字段");
DICT_MAP.put(CREATE_USER_ID, "创建人字段");
DICT_MAP.put(UPDATE_TIME, "更新时间字段");
DICT_MAP.put(UPDATE_USER_ID, "更新人字段");
DICT_MAP.put(LOGIC_DELETE, "逻辑删除字段");
}
/**
* 判断参数是否为当前常量字典的合法值。
*
* @param value 待验证的参数值。
* @return 合法返回true否则false。
*/
public static boolean isValid(Integer value) {
return value != null && DICT_MAP.containsKey(value);
}
/**
* 私有构造函数,明确标识该常量类的作用。
*/
private FieldKind() {
}
}

View File

@@ -0,0 +1,44 @@
package com.flow.demo.common.online.model.constant;
import java.util.HashMap;
import java.util.Map;
/**
* 表单类别常量字典对象。
*
* @author Jerry
* @date 2021-06-06
*/
public final class FormKind {
/**
* 弹框。
*/
public static final int DIALOG = 1;
/**
* 跳页。
*/
public static final int NEW_PAGE = 5;
private static final Map<Object, String> DICT_MAP = new HashMap<>(2);
static {
DICT_MAP.put(DIALOG, "弹框列表");
DICT_MAP.put(NEW_PAGE, "跳页类别");
}
/**
* 判断参数是否为当前常量字典的合法值。
*
* @param value 待验证的参数值。
* @return 合法返回true否则false。
*/
public static boolean isValid(Integer value) {
return value != null && DICT_MAP.containsKey(value);
}
/**
* 私有构造函数,明确标识该常量类的作用。
*/
private FormKind() {
}
}

View File

@@ -0,0 +1,54 @@
package com.flow.demo.common.online.model.constant;
import java.util.HashMap;
import java.util.Map;
/**
* 表单类型常量字典对象。
*
* @author Jerry
* @date 2021-06-06
*/
public final class FormType {
/**
* 查询表单。
*/
public static final int QUERY = 1;
/**
* 编辑表单。
*/
public static final int FORM = 5;
/**
* 流程表单。
*/
public static final int FLOW = 10;
/**
* 流程工单表单。
*/
public static final int FLOW_WORK_ORDER = 11;
private static final Map<Object, String> DICT_MAP = new HashMap<>(2);
static {
DICT_MAP.put(QUERY, "查询表单");
DICT_MAP.put(FORM, "编辑表单");
DICT_MAP.put(FLOW, "流程表单");
DICT_MAP.put(FLOW_WORK_ORDER, "流程工单表单");
}
/**
* 判断参数是否为当前常量字典的合法值。
*
* @param value 待验证的参数值。
* @return 合法返回true否则false。
*/
public static boolean isValid(Integer value) {
return value != null && DICT_MAP.containsKey(value);
}
/**
* 私有构造函数,明确标识该常量类的作用。
*/
private FormType() {
}
}

View File

@@ -0,0 +1,49 @@
package com.flow.demo.common.online.model.constant;
import java.util.HashMap;
import java.util.Map;
/**
* 页面状态常量字典对象。
*
* @author Jerry
* @date 2021-06-06
*/
public final class PageStatus {
/**
* 编辑基础信息。
*/
public static final int BASIC = 0;
/**
* 编辑数据模型。
*/
public static final int DATASOURCE = 1;
/**
* 设计表单。
*/
public static final int FORM_DESIGN = 2;
private static final Map<Object, String> DICT_MAP = new HashMap<>(4);
static {
DICT_MAP.put(BASIC, "编辑基础信息");
DICT_MAP.put(DATASOURCE, "编辑数据模型");
DICT_MAP.put(FORM_DESIGN, "设计表单");
}
/**
* 判断参数是否为当前常量字典的合法值。
*
* @param value 待验证的参数值。
* @return 合法返回true否则false。
*/
public static boolean isValid(Integer value) {
return value != null && DICT_MAP.containsKey(value);
}
/**
* 私有构造函数,明确标识该常量类的作用。
*/
private PageStatus() {
}
}

View File

@@ -0,0 +1,49 @@
package com.flow.demo.common.online.model.constant;
import java.util.HashMap;
import java.util.Map;
/**
* 页面类型常量字典对象。
*
* @author Jerry
* @date 2021-06-06
*/
public final class PageType {
/**
* 业务页面。
*/
public static final int BIZ = 1;
/**
* 统计页面。
*/
public static final int STATS = 5;
/**
* 流程页面。
*/
public static final int FLOW = 10;
private static final Map<Object, String> DICT_MAP = new HashMap<>(2);
static {
DICT_MAP.put(BIZ, "业务页面");
DICT_MAP.put(STATS, "统计页面");
DICT_MAP.put(FLOW, "流程页面");
}
/**
* 判断参数是否为当前常量字典的合法值。
*
* @param value 待验证的参数值。
* @return 合法返回true否则false。
*/
public static boolean isValid(Integer value) {
return value != null && DICT_MAP.containsKey(value);
}
/**
* 私有构造函数,明确标识该常量类的作用。
*/
private PageType() {
}
}

View File

@@ -0,0 +1,44 @@
package com.flow.demo.common.online.model.constant;
import java.util.HashMap;
import java.util.Map;
/**
* 关联类型常量字典对象。
*
* @author Jerry
* @date 2021-06-06
*/
public final class RelationType {
/**
* 一对一关联。
*/
public static final int ONE_TO_ONE = 0;
/**
* 一对多关联。
*/
public static final int ONE_TO_MANY = 1;
private static final Map<Object, String> DICT_MAP = new HashMap<>(2);
static {
DICT_MAP.put(ONE_TO_ONE, "一对一关联");
DICT_MAP.put(ONE_TO_MANY, "一对多关联");
}
/**
* 判断参数是否为当前常量字典的合法值。
*
* @param value 待验证的参数值。
* @return 合法返回true否则false。
*/
public static boolean isValid(Integer value) {
return value != null && DICT_MAP.containsKey(value);
}
/**
* 私有构造函数,明确标识该常量类的作用。
*/
private RelationType() {
}
}

View File

@@ -0,0 +1,69 @@
package com.flow.demo.common.online.model.constant;
import java.util.HashMap;
import java.util.Map;
/**
* 验证规则类型常量字典对象。
*
* @author Jerry
* @date 2021-06-06
*/
public final class RuleType {
/**
* 只允许整数。
*/
public static final int INTEGER_ONLY = 1;
/**
* 只允许数字。
*/
public static final int DIGITAL_ONLY = 2;
/**
* 只允许英文字符。
*/
public static final int LETTER_ONLY = 3;
/**
* 范围验证。
*/
public static final int RANGE = 4;
/**
* 邮箱格式验证。
*/
public static final int EMAIL = 5;
/**
* 手机格式验证。
*/
public static final int MOBILE = 6;
/**
* 自定义验证。
*/
public static final int CUSTOM = 100;
private static final Map<Object, String> DICT_MAP = new HashMap<>(7);
static {
DICT_MAP.put(INTEGER_ONLY, "只允许整数");
DICT_MAP.put(DIGITAL_ONLY, "只允许数字");
DICT_MAP.put(LETTER_ONLY, "只允许英文字符");
DICT_MAP.put(RANGE, "范围验证");
DICT_MAP.put(EMAIL, "邮箱格式验证");
DICT_MAP.put(MOBILE, "手机格式验证");
DICT_MAP.put(CUSTOM, "自定义验证");
}
/**
* 判断参数是否为当前常量字典的合法值。
*
* @param value 待验证的参数值。
* @return 合法返回true否则false。
*/
public static boolean isValid(Integer value) {
return value != null && DICT_MAP.containsKey(value);
}
/**
* 私有构造函数,明确标识该常量类的作用。
*/
private RuleType() {
}
}

View File

@@ -0,0 +1,39 @@
package com.flow.demo.common.online.model.constant;
import java.util.HashMap;
import java.util.Map;
/**
* 在线表单虚拟字段类型常量字典对象。
*
* @author Jerry
* @date 2021-06-06
*/
public final class VirtualType {
/**
* 聚合。
*/
public static final int AGGREGATION = 0;
private static final Map<Object, String> DICT_MAP = new HashMap<>(2);
static {
DICT_MAP.put(AGGREGATION, "聚合");
}
/**
* 判断参数是否为当前常量字典的合法值。
*
* @param value 待验证的参数值。
* @return 合法返回true否则false。
*/
public static boolean isValid(Integer value) {
return value != null && DICT_MAP.containsKey(value);
}
/**
* 私有构造函数,明确标识该常量类的作用。
*/
private VirtualType() {
}
}

View File

@@ -0,0 +1,28 @@
package com.flow.demo.common.online.object;
import com.flow.demo.common.online.model.OnlineColumn;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 表字段数据对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ColumnData {
/**
* 在线表字段对象。
*/
private OnlineColumn column;
/**
* 字段值。
*/
private Object columnValue;
}

View File

@@ -0,0 +1,28 @@
package com.flow.demo.common.online.object;
import lombok.Data;
/**
* 连接表信息对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
public class JoinTableInfo {
/**
* 是否左连接。
*/
private Boolean leftJoin;
/**
* 连接表表名。
*/
private String joinTableName;
/**
* 连接条件。
*/
private String joinCondition;
}

View File

@@ -0,0 +1,41 @@
package com.flow.demo.common.online.object;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* 数据库中的表对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
public class SqlTable {
/**
* 表名称。
*/
private String tableName;
/**
* 表注释。
*/
private String tableComment;
/**
* 创建时间。
*/
private Date createTime;
/**
* 关联的字段列表。
*/
private List<SqlTableColumn> columnList;
/**
* 数据库链接Id。
*/
private Long dblinkId;
}

View File

@@ -0,0 +1,73 @@
package com.flow.demo.common.online.object;
import lombok.Data;
/**
* 数据库中的表字段对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Data
public class SqlTableColumn {
/**
* 表字段名。
*/
private String columnName;
/**
* 表字段类型。
*/
private String columnType;
/**
* 表字段全类型。
*/
private String fullColumnType;
/**
* 字段注释。
*/
private String columnComment;
/**
* 是否为主键。
*/
private Boolean primaryKey;
/**
* 是否自动增长。
*/
private Boolean autoIncrement;
/**
* 是否可以为空值。
*/
private Boolean nullable;
/**
* 字段顺序。
*/
private Integer columnShowOrder;
/**
* 附件信息。
*/
private String extra;
/**
* 字符型字段精度。
*/
private Long stringPrecision;
/**
* 数值型字段精度。
*/
private Integer numericPrecision;
/**
* 缺省值。
*/
private Object columnDefault;
}

View File

@@ -0,0 +1,150 @@
package com.flow.demo.common.online.service;
import com.flow.demo.common.core.base.service.IBaseService;
import com.flow.demo.common.core.object.CallResult;
import com.flow.demo.common.online.model.OnlineColumn;
import com.flow.demo.common.online.model.OnlineColumnRule;
import com.flow.demo.common.online.object.SqlTableColumn;
import java.util.List;
import java.util.Set;
/**
* 字段数据数据操作服务接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineColumnService extends IBaseService<OnlineColumn, Long> {
/**
* 保存新增数据表字段列表。
*
* @param columnList 新增数据表字段对象列表。
* @param onlineTableId 在线表对象的主键Id。
* @return 插入的在线表字段数据。
*/
List<OnlineColumn> saveNewList(List<SqlTableColumn> columnList, Long onlineTableId);
/**
* 更新数据对象。
*
* @param onlineColumn 更新的对象。
* @param originalOnlineColumn 原有数据对象。
* @return 成功返回true否则false。
*/
boolean update(OnlineColumn onlineColumn, OnlineColumn originalOnlineColumn);
/**
* 刷新数据库表字段的数据到在线表字段。
*
* @param sqlTableColumn 源数据库表字段对象。
* @param onlineColumn 被刷新的在线表字段对象。
*/
void refresh(SqlTableColumn sqlTableColumn, OnlineColumn onlineColumn);
/**
* 删除指定数据。
*
* @param tableId 表Id。
* @param columnId 字段Id。
* @return 成功返回true否则false。
*/
boolean remove(Long tableId, Long columnId);
/**
* 批量添加多对多关联关系。
*
* @param onlineColumnRuleList 多对多关联表对象集合。
* @param columnId 主表Id。
*/
void addOnlineColumnRuleList(List<OnlineColumnRule> onlineColumnRuleList, Long columnId);
/**
* 更新中间表数据。
*
* @param onlineColumnRule 中间表对象。
* @return 更新成功与否。
*/
boolean updateOnlineColumnRule(OnlineColumnRule onlineColumnRule);
/**
* 获取中间表数据。
*
* @param columnId 主表Id。
* @param ruleId 从表Id。
* @return 中间表对象。
*/
OnlineColumnRule getOnlineColumnRule(Long columnId, Long ruleId);
/**
* 移除单条多对多关系。
*
* @param columnId 主表Id。
* @param ruleId 从表Id。
* @return 成功返回true否则false。
*/
boolean removeOnlineColumnRule(Long columnId, Long ruleId);
/**
* 当前服务的支持表为从表根据主表的主键Id删除一对多的从表数据。
*
* @param tableId 主表主键Id。
* @return 删除数量。
*/
int removeByTableId(Long tableId);
/**
* 删除指定数据表Id集合中的表字段。
*
* @param tableIdSet 待删除的数据表Id集合。
*/
void removeByTableIdSet(Set<Long> tableIdSet);
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineColumnListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineColumn> getOnlineColumnList(OnlineColumn filter, String orderBy);
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineColumnList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineColumn> getOnlineColumnListWithRelation(OnlineColumn filter, String orderBy);
/**
* 获取指定数据表Id集合的字段对象列表。
*
* @param tableIdSet 指定的数据表Id集合。
* @return 数据表Id集合所包含的字段对象列表。
*/
List<OnlineColumn> getOnlineColumnListByTableIds(Set<Long> tableIdSet);
/**
* 根据表Id和字段列名获取指定字段。
*
* @param tableId 字段所在表Id。
* @param columnName 字段名。
* @return 查询出的字段对象。
*/
OnlineColumn getOnlineColumnByTableIdAndColumnName(Long tableId, String columnName);
/**
* 根据最新对象和原有对象的数据对比,判断关联的字典数据和多对一主表数据是否都是合法数据。
*
* @param onlineColumn 最新数据对象。
* @param originalOnlineColumn 原有数据对象。
* @return 数据全部正确返回true否则false。
*/
CallResult verifyRelatedData(OnlineColumn onlineColumn, OnlineColumn originalOnlineColumn);
}

View File

@@ -0,0 +1,97 @@
package com.flow.demo.common.online.service;
import com.flow.demo.common.core.base.service.IBaseService;
import com.flow.demo.common.core.object.CallResult;
import com.flow.demo.common.online.model.OnlineDatasourceRelation;
import com.flow.demo.common.online.object.SqlTable;
import com.flow.demo.common.online.object.SqlTableColumn;
import java.util.List;
import java.util.Set;
/**
* 数据关联数据操作服务接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineDatasourceRelationService extends IBaseService<OnlineDatasourceRelation, Long> {
/**
* 保存新增对象。
*
* @param relation 新增对象。
* @param slaveSqlTable 新增的关联从数据表对象。
* @param slaveSqlColumn 新增的关联从数据表对象。
* @return 返回新增对象。
*/
OnlineDatasourceRelation saveNew(
OnlineDatasourceRelation relation, SqlTable slaveSqlTable, SqlTableColumn slaveSqlColumn);
/**
* 更新数据对象。
*
* @param relation 更新的对象。
* @param originalRelation 原有数据对象。
* @return 成功返回true否则false。
*/
boolean update(OnlineDatasourceRelation relation, OnlineDatasourceRelation originalRelation);
/**
* 删除指定数据。
*
* @param relationId 主键Id。
* @return 成功返回true否则false。
*/
boolean remove(Long relationId);
/**
* 当前服务的支持表为从表根据主表的主键Id删除一对多的从表数据。
*
* @param datasourceId 主表主键Id。
* @return 删除数量。
*/
int removeByDatasourceId(Long datasourceId);
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineDatasourceRelationListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineDatasourceRelation> getOnlineDatasourceRelationListByDatasourceIds(
OnlineDatasourceRelation filter, String orderBy);
/**
* 获取指定数据源Id集合下的所有数据源关联列表。
*
* @param datasourceIdSet 数据源Id集合。
* @param relationType 关联类型,如果为空,则查询全部类型。
* @return 指定数据源下的所有关联列表。
*/
List<OnlineDatasourceRelation> getOnlineDatasourceRelationListByDatasourceIds(
Set<Long> datasourceIdSet, Integer relationType);
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineDatasourceRelationList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineDatasourceRelation> getOnlineDatasourceRelationListWithRelation(
OnlineDatasourceRelation filter, String orderBy);
/**
* 根据最新对象和原有对象的数据对比,判断关联的字典数据和多对一主表数据是否都是合法数据。
*
* @param relation 最新数据对象。
* @param originalRelation 原有数据对象。
* @return 数据全部正确返回true否则false。
*/
CallResult verifyRelatedData(OnlineDatasourceRelation relation, OnlineDatasourceRelation originalRelation);
}

View File

@@ -0,0 +1,110 @@
package com.flow.demo.common.online.service;
import com.flow.demo.common.core.base.service.IBaseService;
import com.flow.demo.common.online.model.OnlineDatasource;
import com.flow.demo.common.online.model.OnlineDatasourceTable;
import com.flow.demo.common.online.object.SqlTable;
import java.util.List;
import java.util.Set;
/**
* 数据模型数据操作服务接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineDatasourceService extends IBaseService<OnlineDatasource, Long> {
/**
* 保存新增对象。
*
* @param onlineDatasource 新增对象。
* @param sqlTable 新增的数据表对象。
* @param pageId 关联的页面Id。
* @return 返回新增对象。
*/
OnlineDatasource saveNew(OnlineDatasource onlineDatasource, SqlTable sqlTable, Long pageId);
/**
* 更新数据对象。
*
* @param onlineDatasource 更新的对象。
* @param originalOnlineDatasource 原有数据对象。
* @return 成功返回true否则false。
*/
boolean update(OnlineDatasource onlineDatasource, OnlineDatasource originalOnlineDatasource);
/**
* 删除指定数据。
*
* @param datasourceId 主键Id。
* @return 成功返回true否则false。
*/
boolean remove(Long datasourceId);
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineDatasourceListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineDatasource> getOnlineDatasourceList(OnlineDatasource filter, String orderBy);
/**
* 查询指定数据源Id集合的数据源列表。
*
* @param datasourceIdSet 数据源Id集合。
* @return 查询结果集。
*/
List<OnlineDatasource> getOnlineDatasourceList(Set<Long> datasourceIdSet);
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineDatasourceList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineDatasource> getOnlineDatasourceListWithRelation(OnlineDatasource filter, String orderBy);
/**
* 在多对多关系中当前Service的数据表为从表返回不与指定主表主键Id存在对多对关系的列表。
*
* @param pageId 主表主键Id。
* @param filter 从表的过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineDatasource> getNotInOnlineDatasourceListByPageId(Long pageId, OnlineDatasource filter, String orderBy);
/**
* 在多对多关系中当前Service的数据表为从表返回与指定主表主键Id存在对多对关系的列表。
*
* @param pageId 主表主键Id。
* @param filter 从表的过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineDatasource> getOnlineDatasourceListByPageId(Long pageId, OnlineDatasource filter, String orderBy);
/**
* 获取指定数据源Id集合所关联的在线表关联数据。
*
* @param datasourceIdSet 数据源Id集合。
* @return 数据源和数据表的多对多关联列表。
*/
List<OnlineDatasourceTable> getOnlineDatasourceTableList(Set<Long> datasourceIdSet);
/**
* 根据在线表单Id集合获取关联的在线数据源对象列表。
*
* @param readFormIdSet 在线表单Id集合。
* @return 与参数表单Id关联的数据源列表。
*/
List<OnlineDatasource> getOnlineDatasourceListByFormIds(Set<Long> readFormIdSet);
}

View File

@@ -0,0 +1,74 @@
package com.flow.demo.common.online.service;
import com.flow.demo.common.core.base.service.IBaseService;
import com.flow.demo.common.online.model.OnlineDblink;
import com.flow.demo.common.online.object.SqlTable;
import com.flow.demo.common.online.object.SqlTableColumn;
import java.util.List;
/**
* 数据库链接数据操作服务接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineDblinkService extends IBaseService<OnlineDblink, Long> {
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineDblinkListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineDblink> getOnlineDblinkList(OnlineDblink filter, String orderBy);
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineDblinkList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineDblink> getOnlineDblinkListWithRelation(OnlineDblink filter, String orderBy);
/**
* 获取指定DBLink下面的全部数据表。
*
* @param dblink 数据库链接对象。
* @return 全部数据表列表。
*/
List<SqlTable> getDblinkTableList(OnlineDblink dblink);
/**
* 获取指定DBLink下指定表名的数据表对象及其关联字段列表。
*
* @param dblink 数据库链接对象。
* @param tableName 数据库中的数据表名。
* @return 数据表对象。
*/
SqlTable getDblinkTable(OnlineDblink dblink, String tableName);
/**
* 获取指定DBLink下指定表名的字段列表。
*
* @param dblink 数据库链接对象。
* @param tableName 数据库中的数据表名。
* @return 表的字段列表。
*/
List<SqlTableColumn> getDblinkTableColumnList(OnlineDblink dblink, String tableName);
/**
* 获取指定DBLink下指定表的字段对象。
*
* @param dblink 数据库链接对象。
* @param tableName 数据库中的数据表名。
* @param columnName 数据库中的数据表的字段名。
* @return 表的字段对象。
*/
SqlTableColumn getDblinkTableColumn(OnlineDblink dblink, String tableName, String columnName);
}

View File

@@ -0,0 +1,80 @@
package com.flow.demo.common.online.service;
import com.flow.demo.common.core.base.service.IBaseService;
import com.flow.demo.common.core.object.CallResult;
import com.flow.demo.common.online.model.OnlineDict;
import java.util.List;
import java.util.Set;
/**
* 在线表单字典数据操作服务接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineDictService extends IBaseService<OnlineDict, Long> {
/**
* 保存新增对象。
*
* @param onlineDict 新增对象。
* @return 返回新增对象。
*/
OnlineDict saveNew(OnlineDict onlineDict);
/**
* 更新数据对象。
*
* @param onlineDict 更新的对象。
* @param originalOnlineDict 原有数据对象。
* @return 成功返回true否则false。
*/
boolean update(OnlineDict onlineDict, OnlineDict originalOnlineDict);
/**
* 删除指定数据。
*
* @param dictId 主键Id。
* @return 成功返回true否则false。
*/
boolean remove(Long dictId);
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineDictListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineDict> getOnlineDictList(OnlineDict filter, String orderBy);
/**
* 根据指定字典Id集合返回字段对象数据列表。
*
* @param dictIdSet 字典Id集合。
* @return 查询后的字典对象列表。
*/
List<OnlineDict> getOnlineDictList(Set<Long> dictIdSet);
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineDictList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineDict> getOnlineDictListWithRelation(OnlineDict filter, String orderBy);
/**
* 根据最新对象和原有对象的数据对比,判断关联的字典数据和多对一主表数据是否都是合法数据。
*
* @param onlineDict 最新数据对象。
* @param originalOnlineDict 原有数据对象。
* @return 数据全部正确返回true否则false。
*/
CallResult verifyRelatedData(OnlineDict onlineDict, OnlineDict originalOnlineDict);
}

View File

@@ -0,0 +1,115 @@
package com.flow.demo.common.online.service;
import com.flow.demo.common.core.base.service.IBaseService;
import com.flow.demo.common.core.object.CallResult;
import com.flow.demo.common.online.model.OnlineForm;
import com.flow.demo.common.online.model.OnlineFormDatasource;
import java.util.List;
import java.util.Set;
/**
* 在线表单数据操作服务接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineFormService extends IBaseService<OnlineForm, Long> {
/**
* 保存新增对象。
*
* @param onlineForm 新增对象。
* @param datasourceIdSet 在线表单关联的数据源Id集合。
* @return 返回新增对象。
*/
OnlineForm saveNew(OnlineForm onlineForm, Set<Long> datasourceIdSet);
/**
* 更新数据对象。
*
* @param onlineForm 更新的对象。
* @param originalOnlineForm 原有数据对象。
* @param datasourceIdSet 在线表单关联的数据源Id集合。
* @return 成功返回true否则false。
*/
boolean update(OnlineForm onlineForm, OnlineForm originalOnlineForm, Set<Long> datasourceIdSet);
/**
* 删除指定数据。
*
* @param formId 主键Id。
* @return 成功返回true否则false。
*/
boolean remove(Long formId);
/**
* 根据PageId删除其所属的所有表单以及表单关联的数据源数据。
*
* @param pageId 指定的pageId。
* @return 删除数量。
*/
int removeByPageId(Long pageId);
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineFormListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineForm> getOnlineFormList(OnlineForm filter, String orderBy);
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineFormList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineForm> getOnlineFormListWithRelation(OnlineForm filter, String orderBy);
/**
* 获取使用指定数据表的表单列表。
*
* @param tableId 数据表Id。
* @return 使用该数据表的表单列表。
*/
List<OnlineForm> getOnlineFormListByTableId(Long tableId);
/**
* 获取指定表单的数据源列表。
*
* @param formId 指定的表单。
* @return 表单和数据源的多对多关联对象列表。
*/
List<OnlineFormDatasource> getFormDatasourceListByFormId(Long formId);
/**
* 查询正在使用当前数据源的表单。
*
* @param datasourceId 数据源Id。
* @return 正在使用当前数据源的表单列表。
*/
List<OnlineForm> getOnlineFormListByDatasourceId(Long datasourceId);
/**
* 查询指定PageId集合的在线表单列表。
*
* @param pageIdSet 页面Id集合。
* @return 在线表单集合。
*/
List<OnlineForm> getOnlineFormListByPageIds(Set<Long> pageIdSet);
/**
* 根据最新对象和原有对象的数据对比,判断关联的字典数据和多对一主表数据是否都是合法数据。
*
* @param onlineForm 最新数据对象。
* @param originalOnlineForm 原有数据对象。
* @return 数据全部正确返回true否则false。
*/
CallResult verifyRelatedData(OnlineForm onlineForm, OnlineForm originalOnlineForm);
}

View File

@@ -0,0 +1,142 @@
package com.flow.demo.common.online.service;
import com.flow.demo.common.online.dto.OnlineFilterDto;
import com.flow.demo.common.online.model.OnlineColumn;
import com.flow.demo.common.online.model.OnlineDatasourceRelation;
import com.flow.demo.common.online.model.OnlineDict;
import com.flow.demo.common.online.model.OnlineTable;
import com.flow.demo.common.online.object.ColumnData;
import java.util.List;
import java.util.Map;
/**
* 在线表单运行时操作的数据服务接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineOperationService {
/**
* 待插入的所有表数据。
*
* @param table 在线表对象。
* @param columnDataList 数据字段列表。
* @return 主键值。由于自增主键不能获取插入后的主键值因此返回NULL。
*/
Object saveNew(OnlineTable table, List<ColumnData> columnDataList);
/**
* 待插入的主表数据和多个从表数据。
*
* @param masterTable 主表在线表对象。
* @param columnDataList 主表数据字段数据。
* @param slaveDataListMap 多个从表的数据字段数据。
* @return 主表的主键值。由于自增主键不能获取插入后的主键值因此返回NULL。
*/
Object saveNewAndSlaveRelation(
OnlineTable masterTable,
List<ColumnData> columnDataList,
Map<OnlineDatasourceRelation, List<List<ColumnData>>> slaveDataListMap);
/**
* 更新表数据。
*
* @param table 在线表对象。
* @param columnDataList 单条表数据的字段数据列表。
* @return true 更新成功否则false。
*/
boolean update(OnlineTable table, List<ColumnData> columnDataList);
/**
* 更新流程字段的状态。
*
* @param table 数据表。
* @param dataId 主键Id。
* @param column 更新字段。
* @param dataValue 新的数据值。
* @return true 更新成功否则false。
*/
<T> boolean updateColumn(OnlineTable table, String dataId, OnlineColumn column, T dataValue);
/**
* 删除主表数据,及其需要级联删除的一对多关联从表数据。
*
* @param table 表对象。
* @param relationList 一对多关联对象列表。
* @param dataId 主表主键Id值。
* @return true 删除成功否则false。
*/
boolean delete(OnlineTable table, List<OnlineDatasourceRelation> relationList, String dataId);
/**
* 强制删除数据,不会指定逻辑删除,只会物理删除。
*
* @param table 在线表对象。
* @param column 指定的字段。
* @param columnValue 指定字段的值。
*/
void forceDelete(OnlineTable table, OnlineColumn column, String columnValue);
/**
* 从数据源和一对一数据源关联中,动态获取数据。
*
* @param table 主表对象。
* @param oneToOneRelationList 数据源一对一关联列表。
* @param allRelationList 数据源全部关联列表。
* @param dataId 主表主键Id值。
* @return 查询结果。
*/
Map<String, Object> getMasterData(
OnlineTable table,
List<OnlineDatasourceRelation> oneToOneRelationList,
List<OnlineDatasourceRelation> allRelationList,
String dataId);
/**
* 从一对多数据源关联中,动态获取数据。
*
* @param relation 一对多数据源关联对象。
* @param dataId 一对多关联数据主键Id值。
* @return 查询结果。
*/
Map<String, Object> getSlaveData(OnlineDatasourceRelation relation, String dataId);
/**
* 从数据源和一对一数据源关联中,动态获取数据列表。
*
* @param table 主表对象。
* @param oneToOneRelationList 数据源一对一关联列表。
* @param allRelationList 数据源全部关联列表。
* @param filterList 过滤参数列表。
* @param orderBy 排序字符串。
* @return 查询结果集。
*/
List<Map<String, Object>> getMasterDataList(
OnlineTable table,
List<OnlineDatasourceRelation> oneToOneRelationList,
List<OnlineDatasourceRelation> allRelationList,
List<OnlineFilterDto> filterList,
String orderBy);
/**
* 从一对多数据源关联中,动态获取数据列表。
*
* @param relation 一对多数据源关联对象。
* @param filterList 过滤参数列表。
* @param orderBy 排序字符串。
* @return 查询结果集。
*/
List<Map<String, Object>> getSlaveDataList(
OnlineDatasourceRelation relation, List<OnlineFilterDto> filterList, String orderBy);
/**
* 从字典对象指向的数据表中查询数据,并根据参数进行数据过滤。
*
* @param dict 字典对象。
* @param filterList 过滤参数列表。
* @return 查询结果集。
*/
List<Map<String, Object>> getDictDataList(OnlineDict dict, List<OnlineFilterDto> filterList);
}

View File

@@ -0,0 +1,112 @@
package com.flow.demo.common.online.service;
import com.flow.demo.common.core.base.service.IBaseService;
import com.flow.demo.common.online.model.OnlinePage;
import com.flow.demo.common.online.model.OnlinePageDatasource;
import java.util.List;
/**
* 在线表单页面数据操作服务接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlinePageService extends IBaseService<OnlinePage, Long> {
/**
* 保存新增对象。
*
* @param onlinePage 新增对象。
* @return 返回新增对象。
*/
OnlinePage saveNew(OnlinePage onlinePage);
/**
* 更新数据对象。
*
* @param onlinePage 更新的对象。
* @param originalOnlinePage 原有数据对象。
* @return 成功返回true否则false。
*/
boolean update(OnlinePage onlinePage, OnlinePage originalOnlinePage);
/**
* 更新页面对象的发布状态。
*
* @param pageId 页面对象Id。
* @param published 新的状态。
*/
void updatePublished(Long pageId, Boolean published);
/**
* 删除指定数据,及其包含的表单和数据源等。
*
* @param pageId 主键Id。
* @return 成功返回true否则false。
*/
boolean remove(Long pageId);
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlinePageListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlinePage> getOnlinePageList(OnlinePage filter, String orderBy);
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlinePageList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlinePage> getOnlinePageListWithRelation(OnlinePage filter, String orderBy);
/**
* 批量添加多对多关联关系。
*
* @param onlinePageDatasourceList 多对多关联表对象集合。
* @param pageId 主表Id。
*/
void addOnlinePageDatasourceList(List<OnlinePageDatasource> onlinePageDatasourceList, Long pageId);
/**
* 获取中间表数据。
*
* @param pageId 主表Id。
* @param datasourceId 从表Id。
* @return 中间表对象。
*/
OnlinePageDatasource getOnlinePageDatasource(Long pageId, Long datasourceId);
/**
* 获取在线页面和数据源中间表数据列表。
*
* @param pageId 主表Id。
* @return 在线页面和数据源中间表对象列表。
*/
List<OnlinePageDatasource> getOnlinePageDatasourceListByPageId(Long pageId);
/**
* 根据数据源Id返回使用该数据源的OnlinePage对象。
*
* @param datasourceId 数据源Id。
* @return 使用该数据源的页面列表。
*/
List<OnlinePage> getOnlinePageListByDatasourceId(Long datasourceId);
/**
* 移除单条多对多关系。
*
* @param pageId 主表Id。
* @param datasourceId 从表Id。
* @return 成功返回true否则false。
*/
boolean removeOnlinePageDatasource(Long pageId, Long datasourceId);
}

View File

@@ -0,0 +1,91 @@
package com.flow.demo.common.online.service;
import com.flow.demo.common.core.base.service.IBaseService;
import com.flow.demo.common.online.model.OnlineColumnRule;
import com.flow.demo.common.online.model.OnlineRule;
import java.util.List;
import java.util.Set;
/**
* 验证规则数据操作服务接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineRuleService extends IBaseService<OnlineRule, Long> {
/**
* 保存新增对象。
*
* @param onlineRule 新增对象。
* @return 返回新增对象。
*/
OnlineRule saveNew(OnlineRule onlineRule);
/**
* 更新数据对象。
*
* @param onlineRule 更新的对象。
* @param originalOnlineRule 原有数据对象。
* @return 成功返回true否则false。
*/
boolean update(OnlineRule onlineRule, OnlineRule originalOnlineRule);
/**
* 删除指定数据。
*
* @param ruleId 主键Id。
* @return 成功返回true否则false。
*/
boolean remove(Long ruleId);
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineRuleListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineRule> getOnlineRuleList(OnlineRule filter, String orderBy);
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineRuleList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineRule> getOnlineRuleListWithRelation(OnlineRule filter, String orderBy);
/**
* 在多对多关系中当前Service的数据表为从表返回不与指定主表主键Id存在对多对关系的列表。
*
* @param columnId 主表主键Id。
* @param filter 从表的过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineRule> getNotInOnlineRuleListByColumnId(Long columnId, OnlineRule filter, String orderBy);
/**
* 在多对多关系中当前Service的数据表为从表返回与指定主表主键Id存在对多对关系的列表。
*
* @param columnId 主表主键Id。
* @param filter 从表的过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineRule> getOnlineRuleListByColumnId(Long columnId, OnlineRule filter, String orderBy);
/**
* 返回指定字段Id列表关联的字段规则对象列表。
*
* @param columnIdSet 指定的字段Id列表。
* @return 关联的字段规则对象列表。
*/
List<OnlineColumnRule> getOnlineColumnRuleListByColumnIds(Set<Long> columnIdSet);
}

View File

@@ -0,0 +1,95 @@
package com.flow.demo.common.online.service;
import com.flow.demo.common.core.base.service.IBaseService;
import com.flow.demo.common.online.model.OnlineTable;
import com.flow.demo.common.online.object.SqlTable;
import java.util.List;
import java.util.Set;
/**
* 数据表数据操作服务接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineTableService extends IBaseService<OnlineTable, Long> {
/**
* 基于数据库表保存新增对象。
*
* @param sqlTable 数据库表对象。
* @return 返回新增对象。
*/
OnlineTable saveNewFromSqlTable(SqlTable sqlTable);
/**
* 更新数据对象。
*
* @param onlineTable 更新的对象。
* @param originalOnlineTable 原有数据对象。
* @return 成功返回true否则false。
*/
boolean update(OnlineTable onlineTable, OnlineTable originalOnlineTable);
/**
* 删除指定表及其关联的字段数据。
*
* @param tableId 主键Id。
* @return 成功返回true否则false。
*/
boolean remove(Long tableId);
/**
* 删除指定数据表Id集合中的表及其关联字段。
*
* @param tableIdSet 待删除的数据表Id集合。
*/
void removeByTableIdSet(Set<Long> tableIdSet);
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineTableListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineTable> getOnlineTableList(OnlineTable filter, String orderBy);
/**
* 获取指定在线表Id集合的对象列表。
*
* @param tableIdSet 主键Id集合。
* @return 指定的数据表对象列表。
*/
List<OnlineTable> getOnlineTableList(Set<Long> tableIdSet);
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineTableList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineTable> getOnlineTableListWithRelation(OnlineTable filter, String orderBy);
/**
* 根据数据源Id获取该数据源及其关联所引用的数据表列表。
*
* @param datasourceId 指定的数据源Id。
* @return 该数据源及其关联所引用的数据表列表。
*/
List<OnlineTable> getOnlineTableListByDatasourceId(Long datasourceId);
/**
* 从缓存中获取指定的表数据及其关联字段列表。优先从缓存中读取,如果不存在则从数据库中读取,并同步到缓存。
* 该接口方法仅仅用户在线表单的动态数据操作接口,而非在线表单的配置接口。
*
* @param tableId 表主键Id。
* @return 查询后的在线表对象。
*/
OnlineTable getOnlineTableFromCache(Long tableId);
}

View File

@@ -0,0 +1,78 @@
package com.flow.demo.common.online.service;
import com.flow.demo.common.core.base.service.IBaseService;
import com.flow.demo.common.core.object.CallResult;
import com.flow.demo.common.online.model.OnlineVirtualColumn;
import java.util.*;
/**
* 虚拟字段数据操作服务接口。
*
* @author Jerry
* @date 2021-06-06
*/
public interface OnlineVirtualColumnService extends IBaseService<OnlineVirtualColumn, Long> {
/**
* 保存新增对象。
*
* @param onlineVirtualColumn 新增对象。
* @return 返回新增对象。
*/
OnlineVirtualColumn saveNew(OnlineVirtualColumn onlineVirtualColumn);
/**
* 更新数据对象。
*
* @param onlineVirtualColumn 更新的对象。
* @param originalOnlineVirtualColumn 原有数据对象。
* @return 成功返回true否则false。
*/
boolean update(OnlineVirtualColumn onlineVirtualColumn, OnlineVirtualColumn originalOnlineVirtualColumn);
/**
* 删除指定数据。
*
* @param virtualColumnId 主键Id。
* @return 成功返回true否则false。
*/
boolean remove(Long virtualColumnId);
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineVirtualColumnListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineVirtualColumn> getOnlineVirtualColumnList(OnlineVirtualColumn filter, String orderBy);
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineVirtualColumnList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
List<OnlineVirtualColumn> getOnlineVirtualColumnListWithRelation(OnlineVirtualColumn filter, String orderBy);
/**
* 根据数据表的集合,查询关联的虚拟字段数据列表。
* @param tableIdSet 在线数据表Id集合。
* @return 关联的虚拟字段数据列表。
*/
List<OnlineVirtualColumn> getOnlineVirtualColumnListByTableIds(Set<Long> tableIdSet);
/**
* 根据最新对象和原有对象的数据对比,判断关联的字典数据和多对一主表数据是否都是合法数据。
*
* @param virtualColumn 最新数据对象。
* @param originalVirtualColumn 原有数据对象。
* @return 数据全部正确返回true否则false。
*/
CallResult verifyRelatedData(OnlineVirtualColumn virtualColumn, OnlineVirtualColumn originalVirtualColumn);
}

View File

@@ -0,0 +1,365 @@
package com.flow.demo.common.online.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.core.base.service.BaseService;
import com.flow.demo.common.core.object.CallResult;
import com.flow.demo.common.core.object.MyRelationParam;
import com.flow.demo.common.core.util.RedisKeyUtil;
import com.flow.demo.common.sequence.wrapper.IdGeneratorWrapper;
import com.flow.demo.common.online.dao.OnlineColumnMapper;
import com.flow.demo.common.online.dao.OnlineColumnRuleMapper;
import com.flow.demo.common.online.model.OnlineColumn;
import com.flow.demo.common.online.model.OnlineColumnRule;
import com.flow.demo.common.online.model.constant.FieldFilterType;
import com.flow.demo.common.online.object.SqlTableColumn;
import com.flow.demo.common.online.service.OnlineColumnService;
import com.flow.demo.common.online.service.OnlineTableService;
import com.github.pagehelper.Page;
import com.google.common.base.CaseFormat;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* 字段数据数据操作服务类。
*
* @author Jerry
* @date 2021-06-06
*/
@Slf4j
@Service("onlineColumnService")
public class OnlineColumnServiceImpl extends BaseService<OnlineColumn, Long> implements OnlineColumnService {
@Autowired
private OnlineColumnMapper onlineColumnMapper;
@Autowired
private OnlineColumnRuleMapper onlineColumnRuleMapper;
@Autowired
private OnlineTableService onlineTableService;
@Autowired
private IdGeneratorWrapper idGenerator;
@Autowired
private RedissonClient redissonClient;
/**
* 返回当前Service的主表Mapper对象。
*
* @return 主表Mapper对象。
*/
@Override
protected BaseDaoMapper<OnlineColumn> mapper() {
return onlineColumnMapper;
}
/**
* 保存新增数据表字段列表。
*
* @param columnList 新增数据表字段对象列表。
* @param onlineTableId 在线表对象的主键Id。
* @return 插入的在线表字段数据。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public List<OnlineColumn> saveNewList(List<SqlTableColumn> columnList, Long onlineTableId) {
List<OnlineColumn> onlineColumnList = new LinkedList<>();
if (CollUtil.isEmpty(columnList)) {
return onlineColumnList;
}
for (SqlTableColumn column : columnList) {
OnlineColumn onlineColumn = new OnlineColumn();
BeanUtil.copyProperties(column, onlineColumn, false);
onlineColumn.setColumnId(idGenerator.nextLongId());
onlineColumn.setTableId(onlineTableId);
this.setDefault(onlineColumn);
onlineColumnMapper.insert(onlineColumn);
onlineColumnList.add(onlineColumn);
}
return onlineColumnList;
}
/**
* 更新数据对象。
*
* @param onlineColumn 更新的对象。
* @param originalOnlineColumn 原有数据对象。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(OnlineColumn onlineColumn, OnlineColumn originalOnlineColumn) {
this.evictTableCache(onlineColumn.getTableId());
onlineColumn.setUpdateTime(new Date());
onlineColumn.setCreateTime(originalOnlineColumn.getCreateTime());
// 这里重点提示,在执行主表数据更新之前,如果有哪些字段不支持修改操作,请用原有数据对象字段替换当前数据字段。
UpdateWrapper<OnlineColumn> uw = this.createUpdateQueryForNullValue(onlineColumn, onlineColumn.getColumnId());
return onlineColumnMapper.update(onlineColumn, uw) == 1;
}
/**
* 刷新数据库表字段的数据到在线表字段。
*
* @param sqlTableColumn 源数据库表字段对象。
* @param onlineColumn 被刷新的在线表字段对象。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void refresh(SqlTableColumn sqlTableColumn, OnlineColumn onlineColumn) {
this.evictTableCache(onlineColumn.getTableId());
BeanUtil.copyProperties(sqlTableColumn, onlineColumn, false);
String objectFieldName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, onlineColumn.getColumnName());
onlineColumn.setObjectFieldName(objectFieldName);
String objectFieldType = convertToJavaType(onlineColumn.getColumnType());
onlineColumn.setObjectFieldType(objectFieldType);
onlineColumnMapper.updateById(onlineColumn);
}
/**
* 删除指定数据。
*
* @param tableId 表Id。
* @param columnId 字段Id。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean remove(Long tableId, Long columnId) {
this.evictTableCache(tableId);
return onlineColumnMapper.deleteById(columnId) == 1;
}
/**
* 当前服务的支持表为从表根据主表的主键Id删除一对多的从表数据。
*
* @param tableId 主表主键Id。
* @return 删除数量。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public int removeByTableId(Long tableId) {
OnlineColumn deletedObject = new OnlineColumn();
deletedObject.setTableId(tableId);
return onlineColumnMapper.delete(new QueryWrapper<>(deletedObject));
}
/**
* 删除指定数据表Id集合中的表字段。
*
* @param tableIdSet 待删除的数据表Id集合。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void removeByTableIdSet(Set<Long> tableIdSet) {
onlineColumnMapper.delete(new QueryWrapper<OnlineColumn>().lambda().in(OnlineColumn::getTableId, tableIdSet));
}
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineColumnListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineColumn> getOnlineColumnList(OnlineColumn filter, String orderBy) {
return onlineColumnMapper.getOnlineColumnList(filter, orderBy);
}
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineColumnList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineColumn> getOnlineColumnListWithRelation(OnlineColumn filter, String orderBy) {
List<OnlineColumn> resultList = onlineColumnMapper.getOnlineColumnList(filter, orderBy);
// 在缺省生成的代码中如果查询结果resultList不是Page对象说明没有分页那么就很可能是数据导出接口调用了当前方法。
// 为了避免一次性的大量数据关联,规避因此而造成的系统运行性能冲击,这里手动进行了分批次读取,开发者可按需修改该值。
int batchSize = resultList instanceof Page ? 0 : 1000;
this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
return resultList;
}
/**
* 获取指定数据表Id集合的字段对象列表。
*
* @param tableIdSet 指定的数据表Id集合。
* @return 数据表Id集合所包含的字段对象列表。
*/
@Override
public List<OnlineColumn> getOnlineColumnListByTableIds(Set<Long> tableIdSet) {
return onlineColumnMapper.selectList(
new QueryWrapper<OnlineColumn>().lambda().in(OnlineColumn::getTableId, tableIdSet));
}
/**
* 根据表Id和字段列名获取指定字段。
*
* @param tableId 字段所在表Id。
* @param columnName 字段名。
* @return 查询出的字段对象。
*/
@Override
public OnlineColumn getOnlineColumnByTableIdAndColumnName(Long tableId, String columnName) {
OnlineColumn filter = new OnlineColumn();
filter.setTableId(tableId);
filter.setColumnName(columnName);
return onlineColumnMapper.selectOne(new QueryWrapper<>(filter));
}
/**
* 批量添加多对多关联关系。
*
* @param onlineColumnRuleList 多对多关联表对象集合。
* @param columnId 主表Id。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void addOnlineColumnRuleList(List<OnlineColumnRule> onlineColumnRuleList, Long columnId) {
for (OnlineColumnRule onlineColumnRule : onlineColumnRuleList) {
onlineColumnRule.setColumnId(columnId);
onlineColumnRuleMapper.insert(onlineColumnRule);
}
}
/**
* 更新中间表数据。
*
* @param onlineColumnRule 中间表对象。
* @return 更新成功与否。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean updateOnlineColumnRule(OnlineColumnRule onlineColumnRule) {
OnlineColumnRule filter = new OnlineColumnRule();
filter.setColumnId(onlineColumnRule.getColumnId());
filter.setRuleId(onlineColumnRule.getRuleId());
UpdateWrapper<OnlineColumnRule> uw =
BaseService.createUpdateQueryForNullValue(onlineColumnRule, OnlineColumnRule.class);
uw.setEntity(filter);
return onlineColumnRuleMapper.update(onlineColumnRule, uw) > 0;
}
/**
* 获取中间表数据。
*
* @param columnId 主表Id。
* @param ruleId 从表Id。
* @return 中间表对象。
*/
@Override
public OnlineColumnRule getOnlineColumnRule(Long columnId, Long ruleId) {
OnlineColumnRule filter = new OnlineColumnRule();
filter.setColumnId(columnId);
filter.setRuleId(ruleId);
return onlineColumnRuleMapper.selectOne(new QueryWrapper<>(filter));
}
/**
* 移除单条多对多关系。
*
* @param columnId 主表Id。
* @param ruleId 从表Id。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean removeOnlineColumnRule(Long columnId, Long ruleId) {
OnlineColumnRule filter = new OnlineColumnRule();
filter.setColumnId(columnId);
filter.setRuleId(ruleId);
return onlineColumnRuleMapper.delete(new QueryWrapper<>(filter)) > 0;
}
/**
* 根据最新对象和原有对象的数据对比,判断关联的字典数据和多对一主表数据是否都是合法数据。
*
* @param onlineColumn 最新数据对象。
* @param originalOnlineColumn 原有数据对象。
* @return 数据全部正确返回true否则false。
*/
@Override
public CallResult verifyRelatedData(OnlineColumn onlineColumn, OnlineColumn originalOnlineColumn) {
String errorMessageFormat = "数据验证失败,关联的%s并不存在请刷新后重试";
//这里是一对多的验证
if (this.needToVerify(onlineColumn, originalOnlineColumn, OnlineColumn::getTableId)
&& !onlineTableService.existId(onlineColumn.getTableId())) {
return CallResult.error(String.format(errorMessageFormat, "数据表Id"));
}
return CallResult.ok();
}
private void setDefault(OnlineColumn onlineColumn) {
String objectFieldName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, onlineColumn.getColumnName());
onlineColumn.setObjectFieldName(objectFieldName);
String objectFieldType = convertToJavaType(onlineColumn.getColumnType());
onlineColumn.setObjectFieldType(objectFieldType);
onlineColumn.setFilterType(FieldFilterType.NO_FILTER);
onlineColumn.setParentKey(false);
onlineColumn.setDeptFilter(false);
onlineColumn.setUserFilter(false);
Date now = new Date();
onlineColumn.setUpdateTime(now);
onlineColumn.setCreateTime(now);
}
private void evictTableCache(Long tableId) {
String tableIdKey = RedisKeyUtil.makeOnlineTableKey(tableId);
redissonClient.getBucket(tableIdKey).delete();
}
private String convertToJavaType(String columnType) {
if ("varchar".equals(columnType)
|| "char".equals(columnType)
|| "text".equals(columnType)
|| "longtext".equals(columnType)
|| "mediumtext".equals(columnType)
|| "tinytext".equals(columnType)) {
return "String";
}
if ("int".equals(columnType)
|| "mediumint".equals(columnType)
|| "smallint".equals(columnType)
|| "tinyint".equals(columnType)) {
return "Integer";
}
if ("bit".equals(columnType)) {
return "Boolean";
}
if ("bigint".equals(columnType)) {
return "Long";
}
if ("decimal".equals(columnType)) {
return "BigDecimal";
}
if ("float".equals(columnType)
|| "double".equals(columnType)) {
return "Double";
}
if ("date".equals(columnType)
|| "datetime".equals(columnType)
|| "timestamp".equals(columnType)
|| "time".equals(columnType)) {
return "Date";
}
if ("blob".equals(columnType)) {
return "byte[]";
}
throw new RuntimeException("Unsupported Data Type");
}
}

View File

@@ -0,0 +1,255 @@
package com.flow.demo.common.online.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.core.base.service.BaseService;
import com.flow.demo.common.core.object.CallResult;
import com.flow.demo.common.core.object.MyRelationParam;
import com.flow.demo.common.sequence.wrapper.IdGeneratorWrapper;
import com.flow.demo.common.online.dao.OnlineDatasourceRelationMapper;
import com.flow.demo.common.online.dao.OnlineDatasourceTableMapper;
import com.flow.demo.common.online.model.OnlineColumn;
import com.flow.demo.common.online.model.OnlineDatasourceRelation;
import com.flow.demo.common.online.model.OnlineDatasourceTable;
import com.flow.demo.common.online.model.OnlineTable;
import com.flow.demo.common.online.object.SqlTable;
import com.flow.demo.common.online.object.SqlTableColumn;
import com.flow.demo.common.online.service.OnlineColumnService;
import com.flow.demo.common.online.service.OnlineDatasourceRelationService;
import com.flow.demo.common.online.service.OnlineDatasourceService;
import com.flow.demo.common.online.service.OnlineTableService;
import com.github.pagehelper.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Set;
/**
* 数据源关联数据操作服务类。
*
* @author Jerry
* @date 2021-06-06
*/
@Slf4j
@Service("onlineDatasourceRelationService")
public class OnlineDatasourceRelationServiceImpl
extends BaseService<OnlineDatasourceRelation, Long> implements OnlineDatasourceRelationService {
@Autowired
private OnlineDatasourceRelationMapper onlineDatasourceRelationMapper;
@Autowired
private OnlineDatasourceTableMapper onlineDatasourceTableMapper;
@Autowired
private OnlineDatasourceService onlineDatasourceService;
@Autowired
private OnlineColumnService onlineColumnService;
@Autowired
private OnlineTableService onlineTableService;
@Autowired
private IdGeneratorWrapper idGenerator;
/**
* 返回当前Service的主表Mapper对象。
*
* @return 主表Mapper对象。
*/
@Override
protected BaseDaoMapper<OnlineDatasourceRelation> mapper() {
return onlineDatasourceRelationMapper;
}
/**
* 保存新增对象。
*
* @param relation 新增对象。
* @param slaveSqlTable 新增的关联从数据表对象。
* @param slaveSqlColumn 新增的关联从数据表对象。
* @return 返回新增对象。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public OnlineDatasourceRelation saveNew(
OnlineDatasourceRelation relation, SqlTable slaveSqlTable, SqlTableColumn slaveSqlColumn) {
// 查找数据源关联的数据表判断当前关联的从表是否已经存在于zz_online_datasource_table中了。
// 对于同一个数据源及其关联同一个数据表只会被创建一次如果已经和当前数据源的其他Relation
// 作为从表绑定了怎么就可以直接使用这个OnlineTable了否则就会为这个SqlTable创建对应的OnlineTable。
List<OnlineTable> datasourceTableList =
onlineTableService.getOnlineTableListByDatasourceId(relation.getDatasourceId());
OnlineTable relationSlaveTable = null;
OnlineColumn relationSlaveColumn = null;
for (OnlineTable onlineTable : datasourceTableList) {
if (onlineTable.getTableName().equals(slaveSqlTable.getTableName())) {
relationSlaveTable = onlineTable;
relationSlaveColumn = onlineColumnService.getOnlineColumnByTableIdAndColumnName(
onlineTable.getTableId(), slaveSqlColumn.getColumnName());
break;
}
}
if (relationSlaveTable == null) {
relationSlaveTable = onlineTableService.saveNewFromSqlTable(slaveSqlTable);
for (OnlineColumn onlineColumn : relationSlaveTable.getColumnList()) {
if (onlineColumn.getColumnName().equals(slaveSqlColumn.getColumnName())) {
relationSlaveColumn = onlineColumn;
break;
}
}
}
relation.setRelationId(idGenerator.nextLongId());
relation.setSlaveTableId(relationSlaveTable.getTableId());
relation.setSlaveColumnId(relationSlaveColumn.getColumnId());
Date now = new Date();
relation.setUpdateTime(now);
relation.setCreateTime(now);
onlineDatasourceRelationMapper.insert(relation);
OnlineDatasourceTable datasourceTable = new OnlineDatasourceTable();
datasourceTable.setId(idGenerator.nextLongId());
datasourceTable.setDatasourceId(relation.getDatasourceId());
datasourceTable.setRelationId(relation.getRelationId());
datasourceTable.setTableId(relation.getSlaveTableId());
onlineDatasourceTableMapper.insert(datasourceTable);
return relation;
}
/**
* 更新数据对象。
*
* @param relation 更新的对象。
* @param originalRelation 原有数据对象。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(OnlineDatasourceRelation relation, OnlineDatasourceRelation originalRelation) {
relation.setUpdateTime(new Date());
relation.setCreateTime(originalRelation.getCreateTime());
// 这里重点提示,在执行主表数据更新之前,如果有哪些字段不支持修改操作,请用原有数据对象字段替换当前数据字段。
UpdateWrapper<OnlineDatasourceRelation> uw =
this.createUpdateQueryForNullValue(relation, relation.getRelationId());
return onlineDatasourceRelationMapper.update(relation, uw) == 1;
}
/**
* 删除指定数据。
*
* @param relationId 主键Id。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean remove(Long relationId) {
if (onlineDatasourceRelationMapper.deleteById(relationId) != 1) {
return false;
}
OnlineDatasourceTable filter = new OnlineDatasourceTable();
filter.setRelationId(relationId);
QueryWrapper<OnlineDatasourceTable> queryWrapper = new QueryWrapper<>(filter);
OnlineDatasourceTable datasourceTable = onlineDatasourceTableMapper.selectOne(queryWrapper);
onlineDatasourceTableMapper.delete(queryWrapper);
filter = new OnlineDatasourceTable();
filter.setDatasourceId(datasourceTable.getDatasourceId());
filter.setTableId(datasourceTable.getTableId());
// 不在有引用该表的时候,可以删除该数据源关联引用的从表了。
if (onlineDatasourceTableMapper.selectCount(new QueryWrapper<>(filter)) == 0) {
onlineTableService.remove(datasourceTable.getTableId());
}
return true;
}
/**
* 当前服务的支持表为从表根据主表的主键Id删除一对多的从表数据。
*
* @param datasourceId 主表主键Id。
* @return 删除数量。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public int removeByDatasourceId(Long datasourceId) {
OnlineDatasourceRelation deletedObject = new OnlineDatasourceRelation();
deletedObject.setDatasourceId(datasourceId);
return onlineDatasourceRelationMapper.delete(new QueryWrapper<>(deletedObject));
}
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineDatasourceRelationListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineDatasourceRelation> getOnlineDatasourceRelationListByDatasourceIds(
OnlineDatasourceRelation filter, String orderBy) {
return onlineDatasourceRelationMapper.getOnlineDatasourceRelationList(filter, orderBy);
}
/**
* 获取指定数据源Id集合下的所有数据源关联列表。
*
* @param datasourceIdSet 数据源Id集合。
* @param relationType 关联类型,如果为空,则查询全部类型。
* @return 指定数据源下的所有关联列表。
*/
@Override
public List<OnlineDatasourceRelation> getOnlineDatasourceRelationListByDatasourceIds(
Set<Long> datasourceIdSet, Integer relationType) {
QueryWrapper<OnlineDatasourceRelation> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().in(OnlineDatasourceRelation::getDatasourceId, datasourceIdSet);
if (relationType != null) {
queryWrapper.lambda().eq(OnlineDatasourceRelation::getRelationType, relationType);
}
return onlineDatasourceRelationMapper.selectList(queryWrapper);
}
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineDatasourceRelationList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineDatasourceRelation> getOnlineDatasourceRelationListWithRelation(
OnlineDatasourceRelation filter, String orderBy) {
List<OnlineDatasourceRelation> resultList =
onlineDatasourceRelationMapper.getOnlineDatasourceRelationList(filter, orderBy);
// 在缺省生成的代码中如果查询结果resultList不是Page对象说明没有分页那么就很可能是数据导出接口调用了当前方法。
// 为了避免一次性的大量数据关联,规避因此而造成的系统运行性能冲击,这里手动进行了分批次读取,开发者可按需修改该值。
int batchSize = resultList instanceof Page ? 0 : 1000;
this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
return resultList;
}
/**
* 根据最新对象和原有对象的数据对比,判断关联的字典数据和多对一主表数据是否都是合法数据。
*
* @param relation 最新数据对象。
* @param originalRelation 原有数据对象。
* @return 数据全部正确返回true否则false。
*/
@Override
public CallResult verifyRelatedData(
OnlineDatasourceRelation relation, OnlineDatasourceRelation originalRelation) {
String errorMessageFormat = "数据验证失败,关联的%s并不存在请刷新后重试";
if (this.needToVerify(relation, originalRelation, OnlineDatasourceRelation::getMasterColumnId)
&& !onlineColumnService.existId(relation.getMasterColumnId())) {
return CallResult.error(String.format(errorMessageFormat, "主表关联字段Id"));
}
if (this.needToVerify(relation, originalRelation, OnlineDatasourceRelation::getSlaveTableId)
&& !onlineTableService.existId(relation.getSlaveTableId())) {
return CallResult.error(String.format(errorMessageFormat, "从表Id"));
}
if (this.needToVerify(relation, originalRelation, OnlineDatasourceRelation::getSlaveColumnId)
&& !onlineColumnService.existId(relation.getSlaveColumnId())) {
return CallResult.error(String.format(errorMessageFormat, "从表关联字段Id"));
}
return CallResult.ok();
}
}

View File

@@ -0,0 +1,238 @@
package com.flow.demo.common.online.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.core.base.service.BaseService;
import com.flow.demo.common.core.object.MyRelationParam;
import com.flow.demo.common.sequence.wrapper.IdGeneratorWrapper;
import com.flow.demo.common.online.dao.OnlineDatasourceMapper;
import com.flow.demo.common.online.dao.OnlineDatasourceTableMapper;
import com.flow.demo.common.online.dao.OnlinePageDatasourceMapper;
import com.flow.demo.common.online.model.OnlineDatasource;
import com.flow.demo.common.online.model.OnlineDatasourceTable;
import com.flow.demo.common.online.model.OnlinePageDatasource;
import com.flow.demo.common.online.model.OnlineTable;
import com.flow.demo.common.online.object.SqlTable;
import com.flow.demo.common.online.service.OnlineDatasourceRelationService;
import com.flow.demo.common.online.service.OnlineDatasourceService;
import com.flow.demo.common.online.service.OnlineTableService;
import com.github.pagehelper.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 数据模型数据操作服务类。
*
* @author Jerry
* @date 2021-06-06
*/
@Slf4j
@Service("onlineDatasourceService")
public class OnlineDatasourceServiceImpl extends BaseService<OnlineDatasource, Long> implements OnlineDatasourceService {
@Autowired
private OnlineDatasourceMapper onlineDatasourceMapper;
@Autowired
private OnlinePageDatasourceMapper onlinePageDatasourceMapper;
@Autowired
private OnlineDatasourceTableMapper onlineDatasourceTableMapper;
@Autowired
private OnlineTableService onlineTableService;
@Autowired
private OnlineDatasourceRelationService onlineDatasourceRelationService;
@Autowired
private IdGeneratorWrapper idGenerator;
/**
* 返回当前Service的主表Mapper对象。
*
* @return 主表Mapper对象。
*/
@Override
protected BaseDaoMapper<OnlineDatasource> mapper() {
return onlineDatasourceMapper;
}
/**
* 保存新增对象。
*
* @param onlineDatasource 新增对象。
* @param sqlTable 新增的数据表对象。
* @param pageId 关联的页面Id。
* @return 返回新增对象。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public OnlineDatasource saveNew(OnlineDatasource onlineDatasource, SqlTable sqlTable, Long pageId) {
OnlineTable onlineTable = onlineTableService.saveNewFromSqlTable(sqlTable);
onlineDatasource.setDatasourceId(idGenerator.nextLongId());
onlineDatasource.setMasterTableId(onlineTable.getTableId());
Date now = new Date();
onlineDatasource.setUpdateTime(now);
onlineDatasource.setCreateTime(now);
onlineDatasourceMapper.insert(onlineDatasource);
OnlineDatasourceTable datasourceTable = new OnlineDatasourceTable();
datasourceTable.setId(idGenerator.nextLongId());
datasourceTable.setDatasourceId(onlineDatasource.getDatasourceId());
datasourceTable.setTableId(onlineDatasource.getMasterTableId());
onlineDatasourceTableMapper.insert(datasourceTable);
OnlinePageDatasource onlinePageDatasource = new OnlinePageDatasource();
onlinePageDatasource.setId(idGenerator.nextLongId());
onlinePageDatasource.setPageId(pageId);
onlinePageDatasource.setDatasourceId(onlineDatasource.getDatasourceId());
onlinePageDatasourceMapper.insert(onlinePageDatasource);
return onlineDatasource;
}
/**
* 更新数据对象。
*
* @param onlineDatasource 更新的对象。
* @param originalOnlineDatasource 原有数据对象。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(OnlineDatasource onlineDatasource, OnlineDatasource originalOnlineDatasource) {
onlineDatasource.setUpdateTime(new Date());
onlineDatasource.setCreateTime(originalOnlineDatasource.getCreateTime());
// 这里重点提示,在执行主表数据更新之前,如果有哪些字段不支持修改操作,请用原有数据对象字段替换当前数据字段。
UpdateWrapper<OnlineDatasource> uw =
this.createUpdateQueryForNullValue(onlineDatasource, onlineDatasource.getDatasourceId());
return onlineDatasourceMapper.update(onlineDatasource, uw) == 1;
}
/**
* 删除指定数据。
*
* @param datasourceId 主键Id。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean remove(Long datasourceId) {
if (onlineDatasourceMapper.deleteById(datasourceId) == 0) {
return false;
}
onlineDatasourceRelationService.removeByDatasourceId(datasourceId);
// 开始删除多对多父表的关联
OnlinePageDatasource onlinePageDatasource = new OnlinePageDatasource();
onlinePageDatasource.setDatasourceId(datasourceId);
onlinePageDatasourceMapper.delete(new QueryWrapper<>(onlinePageDatasource));
OnlineDatasourceTable filter = new OnlineDatasourceTable();
filter.setDatasourceId(datasourceId);
QueryWrapper<OnlineDatasourceTable> queryWrapper = new QueryWrapper<>(filter);
List<OnlineDatasourceTable> datasourceTableList = onlineDatasourceTableMapper.selectList(queryWrapper);
onlineDatasourceTableMapper.delete(queryWrapper);
Set<Long> tableIdSet = datasourceTableList.stream()
.map(OnlineDatasourceTable::getTableId).collect(Collectors.toSet());
onlineTableService.removeByTableIdSet(tableIdSet);
return true;
}
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineDatasourceListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineDatasource> getOnlineDatasourceList(OnlineDatasource filter, String orderBy) {
return onlineDatasourceMapper.getOnlineDatasourceList(filter, orderBy);
}
/**
* 查询指定数据源Id集合的数据源列表。
*
* @param datasourceIdSet 数据源Id集合。
* @return 查询结果集。
*/
@Override
public List<OnlineDatasource> getOnlineDatasourceList(Set<Long> datasourceIdSet) {
return onlineDatasourceMapper.selectBatchIds(datasourceIdSet);
}
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineDatasourceList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineDatasource> getOnlineDatasourceListWithRelation(OnlineDatasource filter, String orderBy) {
List<OnlineDatasource> resultList = onlineDatasourceMapper.getOnlineDatasourceList(filter, orderBy);
// 在缺省生成的代码中如果查询结果resultList不是Page对象说明没有分页那么就很可能是数据导出接口调用了当前方法。
// 为了避免一次性的大量数据关联,规避因此而造成的系统运行性能冲击,这里手动进行了分批次读取,开发者可按需修改该值。
int batchSize = resultList instanceof Page ? 0 : 1000;
this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
return resultList;
}
/**
* 在多对多关系中当前Service的数据表为从表返回不与指定主表主键Id存在对多对关系的列表。
*
* @param pageId 主表主键Id。
* @param filter 从表的过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineDatasource> getNotInOnlineDatasourceListByPageId(Long pageId, OnlineDatasource filter, String orderBy) {
List<OnlineDatasource> resultList =
onlineDatasourceMapper.getNotInOnlineDatasourceListByPageId(pageId, filter, orderBy);
this.buildRelationForDataList(resultList, MyRelationParam.dictOnly());
return resultList;
}
/**
* 在多对多关系中当前Service的数据表为从表返回与指定主表主键Id存在对多对关系的列表。
*
* @param pageId 主表主键Id。
* @param filter 从表的过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineDatasource> getOnlineDatasourceListByPageId(Long pageId, OnlineDatasource filter, String orderBy) {
List<OnlineDatasource> resultList =
onlineDatasourceMapper.getOnlineDatasourceListByPageId(pageId, filter, orderBy);
this.buildRelationForDataList(resultList, MyRelationParam.dictOnly());
return resultList;
}
/**
* 获取指定数据源Id集合所关联的在线表关联数据。
*
* @param datasourceIdSet 数据源Id集合。
* @return 数据源和数据表的多对多关联列表。
*/
@Override
public List<OnlineDatasourceTable> getOnlineDatasourceTableList(Set<Long> datasourceIdSet) {
return onlineDatasourceTableMapper.selectList(new QueryWrapper<OnlineDatasourceTable>()
.lambda().in(OnlineDatasourceTable::getDatasourceId, datasourceIdSet));
}
/**
* 根据在线表单Id集合获取关联的在线数据源对象列表。
*
* @param formIdSet 在线表单Id集合。
* @return 与参数表单Id关联的数据源列表。
*/
@Override
public List<OnlineDatasource> getOnlineDatasourceListByFormIds(Set<Long> formIdSet) {
return onlineDatasourceMapper.getOnlineDatasourceListByFormIds(formIdSet);
}
}

View File

@@ -0,0 +1,205 @@
package com.flow.demo.common.online.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.core.base.service.BaseService;
import com.flow.demo.common.core.config.DataSourceContextHolder;
import com.flow.demo.common.core.object.MyRelationParam;
import com.flow.demo.common.sequence.wrapper.IdGeneratorWrapper;
import com.flow.demo.common.online.config.OnlineProperties;
import com.flow.demo.common.online.dao.OnlineDblinkMapper;
import com.flow.demo.common.online.model.OnlineDblink;
import com.flow.demo.common.online.object.SqlTable;
import com.flow.demo.common.online.object.SqlTableColumn;
import com.flow.demo.common.online.service.OnlineDblinkService;
import com.github.pagehelper.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 数据库链接数据操作服务类。
*
* @author Jerry
* @date 2021-06-06
*/
@Slf4j
@Service("onlineDblinkService")
public class OnlineDblinkServiceImpl extends BaseService<OnlineDblink, Long> implements OnlineDblinkService {
@Autowired
private OnlineDblinkMapper onlineDblinkMapper;
@Autowired
private IdGeneratorWrapper idGenerator;
@Autowired
private OnlineProperties onlineProperties;
private Map<Serializable, OnlineDblink> dblinkMap;
@PostConstruct
public void loadAllDblink() {
List<OnlineDblink> dblinkList = super.getAllList();
this.dblinkMap = dblinkList.stream().collect(Collectors.toMap(OnlineDblink::getDblinkId, c -> c));
}
/**
* 返回当前Service的主表Mapper对象。
*
* @return 主表Mapper对象。
*/
@Override
protected BaseDaoMapper<OnlineDblink> mapper() {
return onlineDblinkMapper;
}
/**
* 根据主键Id从本地缓存中读取数据库链接信息。
* 这里之所以不考虑缓存补偿,是因为如果出现新的用于在线表单的数据库链接,我们也需要修改当前服务的多数据源配置才能正常工作,
* 否则新OnlineDblink的ConstantType没法保证正常的数据源切换。
*
* @param dblinkId 数据库链接Id。
* @return 查询到的OnlineDblink对象。
*/
@Override
public OnlineDblink getById(Serializable dblinkId) {
return dblinkMap.get(dblinkId);
}
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineDblinkListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineDblink> getOnlineDblinkList(OnlineDblink filter, String orderBy) {
return onlineDblinkMapper.getOnlineDblinkList(filter, orderBy);
}
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineDblinkList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineDblink> getOnlineDblinkListWithRelation(OnlineDblink filter, String orderBy) {
List<OnlineDblink> resultList = onlineDblinkMapper.getOnlineDblinkList(filter, orderBy);
// 在缺省生成的代码中如果查询结果resultList不是Page对象说明没有分页那么就很可能是数据导出接口调用了当前方法。
// 为了避免一次性的大量数据关联,规避因此而造成的系统运行性能冲击,这里手动进行了分批次读取,开发者可按需修改该值。
int batchSize = resultList instanceof Page ? 0 : 1000;
this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
return resultList;
}
/**
* 获取指定DBLink下面的全部数据表。
*
* @param dblink 数据库链接对象。
* @return 全部数据表列表。
*/
@Override
public List<SqlTable> getDblinkTableList(OnlineDblink dblink) {
Integer originalType = DataSourceContextHolder.setDataSourceType(dblink.getDblinkConfigConstant());
try {
List<Map<String, Object>> resultList =
onlineDblinkMapper.getTableListWithPrefix(onlineProperties.getTablePrefix());
List<SqlTable> tableList = new LinkedList<>();
resultList.forEach(r -> {
SqlTable sqlTable = BeanUtil.mapToBean(r, SqlTable.class, false, null);
sqlTable.setDblinkId(dblink.getDblinkId());
tableList.add(sqlTable);
});
return tableList;
} finally {
DataSourceContextHolder.unset(originalType);
}
}
/**
* X
* 获取指定DBLink下指定表名的数据表对象及其关联字段列表。
*
* @param dblink 数据库链接对象。
* @param tableName 数据库中的数据表名。
* @return 数据表对象。
*/
@Override
public SqlTable getDblinkTable(OnlineDblink dblink, String tableName) {
Integer originalType = DataSourceContextHolder.setDataSourceType(dblink.getDblinkConfigConstant());
try {
Map<String, Object> result = onlineDblinkMapper.getTableByName(tableName);
if (result == null) {
return null;
}
SqlTable sqlTable = BeanUtil.mapToBean(result, SqlTable.class, false, null);
sqlTable.setDblinkId(dblink.getDblinkId());
sqlTable.setColumnList(getDblinkTableColumnList(dblink, tableName));
return sqlTable;
} finally {
DataSourceContextHolder.unset(originalType);
}
}
/**
* 获取指定DBLink下指定表名的字段列表。
*
* @param dblink 数据库链接对象。
* @param tableName 表名。
* @return 表的字段列表。
*/
@Override
public List<SqlTableColumn> getDblinkTableColumnList(OnlineDblink dblink, String tableName) {
Integer originalType = DataSourceContextHolder.setDataSourceType(dblink.getDblinkConfigConstant());
try {
List<Map<String, Object>> resultList = onlineDblinkMapper.getTableColumnList(tableName);
List<SqlTableColumn> columnList = new LinkedList<>();
resultList.forEach(r -> {
SqlTableColumn sqlTableColumn =
BeanUtil.mapToBean(r, SqlTableColumn.class, false, null);
sqlTableColumn.setAutoIncrement("auto_increment".equals(sqlTableColumn.getExtra()));
columnList.add(sqlTableColumn);
});
return columnList;
} finally {
DataSourceContextHolder.unset(originalType);
}
}
/**
* 获取指定DBLink下指定表的字段对象。
*
* @param dblink 数据库链接对象。
* @param tableName 数据库中的数据表名。
* @param columnName 数据库中的数据表的字段名。
* @return 表的字段对象。
*/
@Override
public SqlTableColumn getDblinkTableColumn(OnlineDblink dblink, String tableName, String columnName) {
Integer originalType = DataSourceContextHolder.setDataSourceType(dblink.getDblinkConfigConstant());
try {
Map<String, Object> result = onlineDblinkMapper.getTableColumnByName(tableName, columnName);
if (result == null) {
return null;
}
SqlTableColumn sqlTableColumn =
BeanUtil.mapToBean(result, SqlTableColumn.class, false, null);
sqlTableColumn.setAutoIncrement("auto_increment".equals(sqlTableColumn.getExtra()));
return sqlTableColumn;
} finally {
DataSourceContextHolder.unset(originalType);
}
}
}

View File

@@ -0,0 +1,157 @@
package com.flow.demo.common.online.service.impl;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.core.base.service.BaseService;
import com.flow.demo.common.core.object.CallResult;
import com.flow.demo.common.core.object.MyRelationParam;
import com.flow.demo.common.sequence.wrapper.IdGeneratorWrapper;
import com.flow.demo.common.online.dao.OnlineDictMapper;
import com.flow.demo.common.online.model.OnlineDict;
import com.flow.demo.common.online.service.OnlineDblinkService;
import com.flow.demo.common.online.service.OnlineDictService;
import com.github.pagehelper.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Set;
/**
* 在线表单字典数据操作服务类。
*
* @author Jerry
* @date 2021-06-06
*/
@Slf4j
@Service("onlineDictService")
public class OnlineDictServiceImpl extends BaseService<OnlineDict, Long> implements OnlineDictService {
@Autowired
private OnlineDictMapper onlineDictMapper;
@Autowired
private OnlineDblinkService dblinkService;
@Autowired
private IdGeneratorWrapper idGenerator;
/**
* 返回当前Service的主表Mapper对象。
*
* @return 主表Mapper对象。
*/
@Override
protected BaseDaoMapper<OnlineDict> mapper() {
return onlineDictMapper;
}
/**
* 保存新增对象。
*
* @param onlineDict 新增对象。
* @return 返回新增对象。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public OnlineDict saveNew(OnlineDict onlineDict) {
onlineDict.setDictId(idGenerator.nextLongId());
Date now = new Date();
onlineDict.setUpdateTime(now);
onlineDict.setCreateTime(now);
onlineDictMapper.insert(onlineDict);
return onlineDict;
}
/**
* 更新数据对象。
*
* @param onlineDict 更新的对象。
* @param originalOnlineDict 原有数据对象。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(OnlineDict onlineDict, OnlineDict originalOnlineDict) {
onlineDict.setUpdateTime(new Date());
onlineDict.setCreateTime(originalOnlineDict.getCreateTime());
// 这里重点提示,在执行主表数据更新之前,如果有哪些字段不支持修改操作,请用原有数据对象字段替换当前数据字段。
UpdateWrapper<OnlineDict> uw = this.createUpdateQueryForNullValue(onlineDict, onlineDict.getDictId());
return onlineDictMapper.update(onlineDict, uw) == 1;
}
/**
* 删除指定数据。
*
* @param dictId 主键Id。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean remove(Long dictId) {
return onlineDictMapper.deleteById(dictId) == 1;
}
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineDictListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineDict> getOnlineDictList(OnlineDict filter, String orderBy) {
return onlineDictMapper.getOnlineDictList(filter, orderBy);
}
/**
* 根据指定字典Id集合返回字段对象数据列表。
*
* @param dictIdSet 字典Id集合。
* @return 查询后的字典对象列表。
*/
@Override
public List<OnlineDict> getOnlineDictList(Set<Long> dictIdSet) {
return onlineDictMapper.selectBatchIds(dictIdSet);
}
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineDictList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineDict> getOnlineDictListWithRelation(OnlineDict filter, String orderBy) {
List<OnlineDict> resultList = onlineDictMapper.getOnlineDictList(filter, orderBy);
// 在缺省生成的代码中如果查询结果resultList不是Page对象说明没有分页那么就很可能是数据导出接口调用了当前方法。
// 为了避免一次性的大量数据关联,规避因此而造成的系统运行性能冲击,这里手动进行了分批次读取,开发者可按需修改该值。
int batchSize = resultList instanceof Page ? 0 : 1000;
this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
return resultList;
}
/**
* 根据最新对象和原有对象的数据对比,判断关联的字典数据和多对一主表数据是否都是合法数据。
*
* @param onlineDict 最新数据对象。
* @param originalOnlineDict 原有数据对象。
* @return 数据全部正确返回true否则false。
*/
@Override
public CallResult verifyRelatedData(OnlineDict onlineDict, OnlineDict originalOnlineDict) {
String errorMessageFormat = "数据验证失败,关联的%s并不存在请刷新后重试";
//这里是基于字典的验证。
if (this.needToVerify(onlineDict, originalOnlineDict, OnlineDict::getDblinkId)
&& !dblinkService.existId(onlineDict.getDblinkId())) {
return CallResult.error(String.format(errorMessageFormat, "数据库链接主键id"));
}
return CallResult.ok();
}
}

View File

@@ -0,0 +1,262 @@
package com.flow.demo.common.online.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.core.base.service.BaseService;
import com.flow.demo.common.core.object.CallResult;
import com.flow.demo.common.core.object.MyRelationParam;
import com.flow.demo.common.sequence.wrapper.IdGeneratorWrapper;
import com.flow.demo.common.online.dao.OnlineFormDatasourceMapper;
import com.flow.demo.common.online.dao.OnlineFormMapper;
import com.flow.demo.common.online.model.OnlineForm;
import com.flow.demo.common.online.model.OnlineFormDatasource;
import com.flow.demo.common.online.service.OnlineFormService;
import com.flow.demo.common.online.service.OnlinePageService;
import com.flow.demo.common.online.service.OnlineTableService;
import com.github.pagehelper.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
/**
* 在线表单数据操作服务类。
*
* @author Jerry
* @date 2021-06-06
*/
@Slf4j
@Service("onlineFormService")
public class OnlineFormServiceImpl extends BaseService<OnlineForm, Long> implements OnlineFormService {
@Autowired
private OnlineFormMapper onlineFormMapper;
@Autowired
private OnlineFormDatasourceMapper onlineFormDatasourceMapper;
@Autowired
private OnlineTableService onlineTableService;
@Autowired
private OnlinePageService onlinePageService;
@Autowired
private IdGeneratorWrapper idGenerator;
/**
* 返回当前Service的主表Mapper对象。
*
* @return 主表Mapper对象。
*/
@Override
protected BaseDaoMapper<OnlineForm> mapper() {
return onlineFormMapper;
}
/**
* 保存新增对象。
*
* @param onlineForm 新增对象。
* @param datasourceIdSet 在线表单关联的数据源Id集合。
* @return 返回新增对象。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public OnlineForm saveNew(OnlineForm onlineForm, Set<Long> datasourceIdSet) {
onlineForm.setFormId(idGenerator.nextLongId());
Date now = new Date();
onlineForm.setUpdateTime(now);
onlineForm.setCreateTime(now);
onlineFormMapper.insert(onlineForm);
if (CollUtil.isNotEmpty(datasourceIdSet)) {
for (Long datasourceId : datasourceIdSet) {
OnlineFormDatasource onlineFormDatasource = new OnlineFormDatasource();
onlineFormDatasource.setId(idGenerator.nextLongId());
onlineFormDatasource.setFormId(onlineForm.getFormId());
onlineFormDatasource.setDatasourceId(datasourceId);
onlineFormDatasourceMapper.insert(onlineFormDatasource);
}
}
return onlineForm;
}
/**
* 更新数据对象。
*
* @param onlineForm 更新的对象。
* @param originalOnlineForm 原有数据对象。
* @param datasourceIdSet 在线表单关联的数据源Id集合。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(OnlineForm onlineForm, OnlineForm originalOnlineForm, Set<Long> datasourceIdSet) {
onlineForm.setUpdateTime(new Date());
onlineForm.setCreateTime(originalOnlineForm.getCreateTime());
// 这里重点提示,在执行主表数据更新之前,如果有哪些字段不支持修改操作,请用原有数据对象字段替换当前数据字段。
UpdateWrapper<OnlineForm> uw = this.createUpdateQueryForNullValue(onlineForm, onlineForm.getFormId());
if (onlineFormMapper.update(onlineForm, uw) != 1) {
return false;
}
OnlineFormDatasource formDatasourceFilter = new OnlineFormDatasource();
formDatasourceFilter.setFormId(onlineForm.getFormId());
onlineFormDatasourceMapper.delete(new QueryWrapper<>(formDatasourceFilter));
if (CollUtil.isNotEmpty(datasourceIdSet)) {
for (Long datasourceId : datasourceIdSet) {
OnlineFormDatasource onlineFormDatasource = new OnlineFormDatasource();
onlineFormDatasource.setId(idGenerator.nextLongId());
onlineFormDatasource.setFormId(onlineForm.getFormId());
onlineFormDatasource.setDatasourceId(datasourceId);
onlineFormDatasourceMapper.insert(onlineFormDatasource);
}
}
return true;
}
/**
* 删除指定数据。
*
* @param formId 主键Id。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean remove(Long formId) {
if (onlineFormMapper.deleteById(formId) != 1) {
return false;
}
OnlineFormDatasource formDatasourceFilter = new OnlineFormDatasource();
formDatasourceFilter.setFormId(formId);
onlineFormDatasourceMapper.delete(new QueryWrapper<>(formDatasourceFilter));
return true;
}
/**
* 根据PageId删除其所属的所有表单以及表单关联的数据源数据。
*
* @param pageId 指定的pageId。
* @return 删除数量。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public int removeByPageId(Long pageId) {
OnlineForm filter = new OnlineForm();
filter.setPageId(pageId);
List<OnlineForm> formList = onlineFormMapper.selectList(new QueryWrapper<>(filter));
Set<Long> formIdSet = formList.stream().map(OnlineForm::getFormId).collect(Collectors.toSet());
if (CollUtil.isNotEmpty(formIdSet)) {
onlineFormDatasourceMapper.delete(
new QueryWrapper<OnlineFormDatasource>().lambda().in(OnlineFormDatasource::getFormId, formIdSet));
}
return onlineFormMapper.delete(new QueryWrapper<>(filter));
}
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineFormListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineForm> getOnlineFormList(OnlineForm filter, String orderBy) {
return onlineFormMapper.getOnlineFormList(filter, orderBy);
}
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineFormList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineForm> getOnlineFormListWithRelation(OnlineForm filter, String orderBy) {
List<OnlineForm> resultList = onlineFormMapper.getOnlineFormList(filter, orderBy);
// 在缺省生成的代码中如果查询结果resultList不是Page对象说明没有分页那么就很可能是数据导出接口调用了当前方法。
// 为了避免一次性的大量数据关联,规避因此而造成的系统运行性能冲击,这里手动进行了分批次读取,开发者可按需修改该值。
int batchSize = resultList instanceof Page ? 0 : 1000;
this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
return resultList;
}
/**
* 获取使用指定数据表的表单列表。
*
* @param tableId 数据表Id。
* @return 使用该数据表的表单列表。
*/
@Override
public List<OnlineForm> getOnlineFormListByTableId(Long tableId) {
OnlineForm filter = new OnlineForm();
filter.setMasterTableId(tableId);
return onlineFormMapper.selectList(new QueryWrapper<>(filter));
}
/**
* 获取指定表单的数据源列表。
*
* @param formId 指定的表单。
* @return 表单和数据源的多对多关联对象列表。
*/
@Override
public List<OnlineFormDatasource> getFormDatasourceListByFormId(Long formId) {
return onlineFormDatasourceMapper.selectList(
new QueryWrapper<OnlineFormDatasource>().lambda().eq(OnlineFormDatasource::getFormId, formId));
}
/**
* 查询正在使用当前数据源的表单。
*
* @param datasourceId 数据源Id。
* @return 正在使用当前数据源的表单列表。
*/
@Override
public List<OnlineForm> getOnlineFormListByDatasourceId(Long datasourceId) {
List<OnlineFormDatasource> formDatasourceList = onlineFormDatasourceMapper.selectList(
new QueryWrapper<OnlineFormDatasource>().lambda().eq(OnlineFormDatasource::getDatasourceId, datasourceId));
if (CollUtil.isEmpty(formDatasourceList)) {
return new LinkedList<>();
}
Collection<Long> formIdSet = formDatasourceList.stream()
.map(OnlineFormDatasource::getFormId).collect(Collectors.toSet());
return onlineFormMapper.selectList(
new QueryWrapper<OnlineForm>().lambda().in(OnlineForm::getFormId, formIdSet));
}
@Override
public List<OnlineForm> getOnlineFormListByPageIds(Set<Long> pageIdSet) {
LambdaQueryWrapper<OnlineForm> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(OnlineForm::getPageId, pageIdSet);
return onlineFormMapper.selectList(queryWrapper);
}
/**
* 根据最新对象和原有对象的数据对比,判断关联的字典数据和多对一主表数据是否都是合法数据。
*
* @param onlineForm 最新数据对象。
* @param originalOnlineForm 原有数据对象。
* @return 数据全部正确返回true否则false。
*/
@Override
public CallResult verifyRelatedData(OnlineForm onlineForm, OnlineForm originalOnlineForm) {
String errorMessageFormat = "数据验证失败,关联的%s并不存在请刷新后重试";
//这里是基于字典的验证。
if (this.needToVerify(onlineForm, originalOnlineForm, OnlineForm::getMasterTableId)
&& !onlineTableService.existId(onlineForm.getMasterTableId())) {
return CallResult.error(String.format(errorMessageFormat, "表单主表id"));
}
//这里是一对多的验证
if (this.needToVerify(onlineForm, originalOnlineForm, OnlineForm::getPageId)
&& !onlinePageService.existId(onlineForm.getPageId())) {
return CallResult.error(String.format(errorMessageFormat, "页面id"));
}
return CallResult.ok();
}
}

View File

@@ -0,0 +1,973 @@
package com.flow.demo.common.online.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.flow.demo.common.core.annotation.MyDataSourceResolver;
import com.flow.demo.common.core.constant.AggregationType;
import com.flow.demo.common.core.exception.NoDataPermException;
import com.flow.demo.common.core.constant.GlobalDeletedFlag;
import com.flow.demo.common.core.object.MyWhereCriteria;
import com.flow.demo.common.core.object.TokenData;
import com.flow.demo.common.core.object.Tuple2;
import com.flow.demo.common.core.util.RedisKeyUtil;
import com.flow.demo.common.datafilter.constant.DataPermRuleType;
import com.flow.demo.common.datafilter.config.DataFilterProperties;
import com.flow.demo.common.online.model.constant.*;
import com.flow.demo.common.online.service.OnlineVirtualColumnService;
import com.flow.demo.common.online.util.OnlineOperationHelper;
import com.flow.demo.common.sequence.wrapper.IdGeneratorWrapper;
import com.flow.demo.common.online.util.OnlineDataSourceResolver;
import com.flow.demo.common.online.util.OnlineConstant;
import com.flow.demo.common.online.dao.OnlineOperationMapper;
import com.flow.demo.common.online.dto.OnlineFilterDto;
import com.flow.demo.common.online.model.*;
import com.flow.demo.common.online.object.ColumnData;
import com.flow.demo.common.online.object.JoinTableInfo;
import com.flow.demo.common.online.service.OnlineDictService;
import com.flow.demo.common.online.service.OnlineOperationService;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
/**
* 在线表单运行时数据操作服务类。
*
* @author Jerry
* @date 2021-06-06
*/
@MyDataSourceResolver(resolver = OnlineDataSourceResolver.class)
@Slf4j
@Service("onlineOperationService")
public class OnlineOperationServiceImpl implements OnlineOperationService {
@Autowired
private OnlineOperationMapper onlineOperationMapper;
@Autowired
private OnlineDictService onlineDictService;
@Autowired
private OnlineVirtualColumnService onlineVirtualColumnService;
@Autowired
private OnlineOperationHelper onlineOperationHelper;
@Autowired
private IdGeneratorWrapper idGenerator;
@Autowired
private RedissonClient redissonClient;
@Autowired
private DataFilterProperties dataFilterProperties;
/**
* 聚合返回数据中,聚合键的常量字段名。
* 如select groupColumn groupedKey, max(aggregationColumn) aggregatedValue。
*/
public static final String KEY_NAME = "groupedKey";
/**
* 聚合返回数据中,聚合值的常量字段名。
* 如select groupColumn groupedKey, max(aggregationColumn) aggregatedValue。
*/
public static final String VALUE_NAME = "aggregatedValue";
@Transactional(rollbackFor = Exception.class)
@Override
public Object saveNew(OnlineTable table, List<ColumnData> columnDataList) {
String tableName = table.getTableName();
String columnNames = this.makeColumnNames(columnDataList);
List<Object> columnValueList = new LinkedList<>();
Object id = null;
// 这里逐个处理每一行数据特别是非自增主键、createUserId、createTime、逻辑删除等特殊属性的字段。
for (ColumnData columnData : columnDataList) {
if (!columnData.getColumn().getAutoIncrement()) {
this.makeupColumnValue(columnData);
columnValueList.add(columnData.getColumnValue());
if (columnData.getColumn().getPrimaryKey()) {
id = columnData.getColumnValue();
}
}
}
onlineOperationMapper.insert(tableName, columnNames, columnValueList);
return id;
}
@Transactional(rollbackFor = Exception.class)
@Override
public Object saveNewAndSlaveRelation(
OnlineTable masterTable,
List<ColumnData> columnDataList,
Map<OnlineDatasourceRelation, List<List<ColumnData>>> slaveDataListMap) {
Object id = this.saveNew(masterTable, columnDataList);
// 迭代多个一对多关联。
for (Map.Entry<OnlineDatasourceRelation, List<List<ColumnData>>> entry : slaveDataListMap.entrySet()) {
Long masterColumnId = entry.getKey().getMasterColumnId();
ColumnData masterColumnData = null;
for (ColumnData columnData : columnDataList) {
if (columnData.getColumn().getColumnId().equals(masterColumnId)) {
masterColumnData = columnData;
break;
}
}
Long slaveColumnId = entry.getKey().getSlaveColumnId();
// 迭代一对多关联中的数据集合
for (List<ColumnData> slaveColumnDataList : entry.getValue()) {
// 迭代一对多关联记录的字段列表。
for (ColumnData slaveColumnData : slaveColumnDataList) {
if (slaveColumnData.getColumn().getColumnId().equals(slaveColumnId)) {
slaveColumnData.setColumnValue(masterColumnData.getColumnValue());
break;
}
}
this.saveNew(entry.getKey().getSlaveTable(), slaveColumnDataList);
}
}
return id;
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(OnlineTable table, List<ColumnData> columnDataList) {
String tableName = table.getTableName();
List<ColumnData> updateColumnList = new LinkedList<>();
List<ColumnData> whereColumnList = new LinkedList<>();
for (ColumnData columnData : columnDataList) {
this.makeupColumnValue(columnData);
// 对于以下几种类型的字段,忽略更新。
if (columnData.getColumn().getPrimaryKey()
|| ObjectUtil.equal(columnData.getColumn().getFieldKind(), FieldKind.LOGIC_DELETE)) {
whereColumnList.add(columnData);
continue;
}
if (ObjectUtil.notEqual(columnData.getColumn().getFieldKind(), FieldKind.CREATE_TIME)
&& ObjectUtil.notEqual(columnData.getColumn().getFieldKind(), FieldKind.CREATE_USER_ID)) {
updateColumnList.add(columnData);
}
}
if (CollUtil.isEmpty(updateColumnList)) {
return true;
}
String dataPermFilter = this.buildDataPermFilter(table);
return onlineOperationMapper.update(tableName, updateColumnList, whereColumnList, dataPermFilter) == 1;
}
@Transactional(rollbackFor = Exception.class)
@Override
public <T> boolean updateColumn(OnlineTable table, String dataId, OnlineColumn column, T dataValue) {
List<ColumnData> whereColumnList = new LinkedList<>();
if (table.getLogicDeleteColumn() != null) {
ColumnData logicDeleteColumnData = new ColumnData();
logicDeleteColumnData.setColumn(table.getLogicDeleteColumn());
logicDeleteColumnData.setColumnValue(GlobalDeletedFlag.NORMAL);
whereColumnList.add(logicDeleteColumnData);
}
ColumnData primaryKeyColumnData = new ColumnData();
primaryKeyColumnData.setColumn(table.getPrimaryKeyColumn());
primaryKeyColumnData.setColumnValue(
onlineOperationHelper.convertToTypeValue(table.getPrimaryKeyColumn(), dataId));
whereColumnList.add(primaryKeyColumnData);
List<ColumnData> updateColumnList = new LinkedList<>();
ColumnData updateColumnData = new ColumnData();
updateColumnData.setColumn(column);
updateColumnData.setColumnValue(dataValue);
updateColumnList.add(updateColumnData);
List<OnlineFilterDto> filterList =
this.makeDefaultFilter(table, table.getPrimaryKeyColumn(), dataId);
String dataPermFilter = this.buildDataPermFilter(table);
return onlineOperationMapper.update(
table.getTableName(), updateColumnList, whereColumnList, dataPermFilter) == 1;
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean delete(OnlineTable table, List<OnlineDatasourceRelation> relationList, String dataId) {
Map<String, Object> masterData = null;
if (CollUtil.isNotEmpty(relationList)) {
for (OnlineDatasourceRelation relation : relationList) {
if (relation.getCascadeDelete()
&& !relation.getMasterColumnId().equals(table.getPrimaryKeyColumn().getColumnId())) {
masterData = getMasterData(table, null, null, dataId);
break;
}
}
}
List<OnlineFilterDto> filterList =
this.makeDefaultFilter(table, table.getPrimaryKeyColumn(), dataId);
String dataPermFilter = this.buildDataPermFilter(table);
if (table.getLogicDeleteColumn() == null) {
if (onlineOperationMapper.delete(table.getTableName(), filterList, dataPermFilter) != 1) {
return false;
}
} else {
if (!this.doLogicDelete(table, table.getPrimaryKeyColumn(), dataId, dataPermFilter)) {
return false;
}
}
if (CollUtil.isEmpty(relationList)) {
return true;
}
for (OnlineDatasourceRelation relation : relationList) {
if (!relation.getCascadeDelete()) {
continue;
}
OnlineTable slaveTable = relation.getSlaveTable();
OnlineColumn slaveColumn =
relation.getSlaveTable().getColumnMap().get(relation.getSlaveColumnId());
String columnValue = dataId;
if (!relation.getMasterColumnId().equals(table.getPrimaryKeyColumn().getColumnId())) {
OnlineColumn relationMasterColumn = table.getColumnMap().get(relation.getMasterColumnId());
columnValue = masterData.get(relationMasterColumn.getColumnName()).toString();
}
if (slaveTable.getLogicDeleteColumn() == null) {
List<OnlineFilterDto> slaveFilterList =
this.makeDefaultFilter(relation.getSlaveTable(), slaveColumn, columnValue);
onlineOperationMapper.delete(slaveTable.getTableName(), slaveFilterList, null);
} else {
this.doLogicDelete(slaveTable, slaveColumn, columnValue, null);
}
}
return true;
}
@Transactional(rollbackFor = Exception.class)
@Override
public void forceDelete(OnlineTable table, OnlineColumn column, String columnValue) {
List<OnlineFilterDto> filterList = this.makeDefaultFilter(table, column, columnValue);
onlineOperationMapper.delete(table.getTableName(), filterList, null);
}
@Override
public Map<String, Object> getMasterData(
OnlineTable table,
List<OnlineDatasourceRelation> oneToOneRelationList,
List<OnlineDatasourceRelation> allRelationList,
String dataId) {
List<OnlineFilterDto> filterList =
this.makeDefaultFilter(table, table.getPrimaryKeyColumn(), dataId);
// 组件表关联数据。
List<JoinTableInfo> joinInfoList = this.makeJoinInfoList(table, oneToOneRelationList);
// 拼接关联表的select fields字段。
String selectFields = this.makeSelectFields(table, oneToOneRelationList);
String dataPermFilter = this.buildDataPermFilter(table);
List<Map<String, Object>> resultList = onlineOperationMapper.getList(
table.getTableName(), joinInfoList, selectFields, filterList, dataPermFilter, null);
this.buildDataListWithDict(resultList, table, oneToOneRelationList);
if (CollUtil.isEmpty(resultList)) {
return null;
}
if (CollUtil.isNotEmpty(allRelationList)) {
// 针对一对多和多对多关联,计算虚拟聚合字段。
List<OnlineDatasourceRelation> toManyRelationList = allRelationList.stream()
.filter(r -> !r.getRelationType().equals(RelationType.ONE_TO_ONE)).collect(Collectors.toList());
this.buildVirtualColumn(resultList, table, toManyRelationList);
}
return resultList.get(0);
}
@Override
public Map<String, Object> getSlaveData(OnlineDatasourceRelation relation, String dataId) {
OnlineTable slaveTable = relation.getSlaveTable();
List<OnlineFilterDto> filterList =
this.makeDefaultFilter(slaveTable, slaveTable.getPrimaryKeyColumn(), dataId);
// 拼接关联表的select fields字段。
String selectFields = this.makeSelectFields(slaveTable, relation.getVariableName());
String dataPermFilter = this.buildDataPermFilter(slaveTable);
List<Map<String, Object>> resultList = onlineOperationMapper.getList(
slaveTable.getTableName(), null, selectFields, filterList, dataPermFilter, null);
this.buildDataListWithDict(resultList, slaveTable, relation.getVariableName());
return CollUtil.isEmpty(resultList) ? null : resultList.get(0);
}
@Override
public List<Map<String, Object>> getMasterDataList(
OnlineTable table,
List<OnlineDatasourceRelation> oneToOneRelationList,
List<OnlineDatasourceRelation> allRelationList,
List<OnlineFilterDto> filterList,
String orderBy) {
// 如果主表中包含逻辑删除,需要在这里补充到过滤字段中。
if (table.getLogicDeleteColumn() != null) {
if (filterList == null) {
filterList = new LinkedList<>();
}
OnlineFilterDto filter = new OnlineFilterDto();
filter.setTableName(table.getTableName());
filter.setColumnName(table.getLogicDeleteColumn().getColumnName());
filter.setColumnValue(GlobalDeletedFlag.NORMAL);
filterList.add(filter);
}
// 组件表关联数据。
List<JoinTableInfo> joinInfoList = this.makeJoinInfoList(table, oneToOneRelationList);
// 拼接关联表的select fields字段。
String selectFields = this.makeSelectFields(table, oneToOneRelationList);
String dataPermFilter = this.buildDataPermFilter(table);
List<Map<String, Object>> resultList = onlineOperationMapper.getList(
table.getTableName(), joinInfoList, selectFields, filterList, dataPermFilter, orderBy);
this.buildDataListWithDict(resultList, table, oneToOneRelationList);
// 针对一对多和多对多关联,计算虚拟聚合字段。
if (CollUtil.isNotEmpty(allRelationList)) {
List<OnlineDatasourceRelation> toManyRelationList = allRelationList.stream()
.filter(r -> !r.getRelationType().equals(RelationType.ONE_TO_ONE)).collect(Collectors.toList());
this.buildVirtualColumn(resultList, table, toManyRelationList);
}
return resultList;
}
@Override
public List<Map<String, Object>> getSlaveDataList(
OnlineDatasourceRelation relation, List<OnlineFilterDto> filterList, String orderBy) {
OnlineTable slaveTable = relation.getSlaveTable();
// 如果主表中包含逻辑删除,需要在这里补充到过滤字段中。
if (slaveTable.getLogicDeleteColumn() != null) {
if (filterList == null) {
filterList = new LinkedList<>();
}
OnlineFilterDto filter = new OnlineFilterDto();
filter.setTableName(slaveTable.getTableName());
filter.setColumnName(slaveTable.getLogicDeleteColumn().getColumnName());
filter.setColumnValue(GlobalDeletedFlag.NORMAL);
filterList.add(filter);
}
// 拼接关联表的select fields字段。
String selectFields = this.makeSelectFields(slaveTable, relation.getVariableName());
String dataPermFilter = this.buildDataPermFilter(slaveTable);
List<Map<String, Object>> resultList = onlineOperationMapper.getList(
slaveTable.getTableName(), null, selectFields, filterList, dataPermFilter, orderBy);
this.buildDataListWithDict(resultList, slaveTable, relation.getVariableName());
return resultList;
}
@Override
public List<Map<String, Object>> getDictDataList(OnlineDict dict, List<OnlineFilterDto> filterList) {
if (StrUtil.isNotEmpty(dict.getDeletedColumnName())) {
if (filterList == null) {
filterList = new LinkedList<>();
}
OnlineFilterDto filter = new OnlineFilterDto();
filter.setColumnName(dict.getDeletedColumnName());
filter.setColumnValue(GlobalDeletedFlag.NORMAL);
filterList.add(filter);
}
String selectFields = this.makeDictSelectFields(dict, false);
String dataPermFilter = this.buildDataPermFilter(
dict.getTableName(), dict.getDeptFilterColumnName(), dict.getUserFilterColumnName());
return onlineOperationMapper.getDictList(dict.getTableName(), selectFields, filterList, dataPermFilter);
}
private void buildVirtualColumn(
List<Map<String, Object>> resultList, OnlineTable table, List<OnlineDatasourceRelation> relationList) {
if (CollUtil.isEmpty(resultList) || CollUtil.isEmpty(relationList)) {
return;
}
OnlineVirtualColumn virtualColumnFilter = new OnlineVirtualColumn();
virtualColumnFilter.setTableId(table.getTableId());
virtualColumnFilter.setVirtualType(VirtualType.AGGREGATION);
List<OnlineVirtualColumn> virtualColumnList =
onlineVirtualColumnService.getOnlineVirtualColumnList(virtualColumnFilter, null);
if (CollUtil.isEmpty(virtualColumnList)) {
return;
}
Map<Long, OnlineDatasourceRelation> relationMap =
relationList.stream().collect(Collectors.toMap(OnlineDatasourceRelation::getRelationId, r -> r));
for (OnlineVirtualColumn virtualColumn : virtualColumnList) {
OnlineDatasourceRelation relation = relationMap.get(virtualColumn.getRelationId());
if (relation.getRelationType().equals(RelationType.ONE_TO_MANY)) {
this.doBuildVirtualColumnForOneToMany(table, resultList, virtualColumn, relation);
}
}
}
private void doBuildVirtualColumnForOneToMany(
OnlineTable masterTable,
List<Map<String, Object>> resultList,
OnlineVirtualColumn virtualColumn,
OnlineDatasourceRelation relation) {
String slaveTableName = relation.getSlaveTable().getTableName();
OnlineColumn slaveColumn =
relation.getSlaveTable().getColumnMap().get(relation.getSlaveColumnId());
String slaveColumnName = slaveColumn.getColumnName();
OnlineColumn aggregationColumn =
relation.getSlaveTable().getColumnMap().get(virtualColumn.getAggregationColumnId());
String aggregationColumnName = aggregationColumn.getColumnName();
Tuple2<String, String> selectAndGroupByTuple = makeSelectListAndGroupByClause(
slaveTableName, slaveColumnName, slaveTableName, aggregationColumnName, virtualColumn.getAggregationType());
String selectList = selectAndGroupByTuple.getFirst();
String groupBy = selectAndGroupByTuple.getSecond();
// 开始组装过滤从句。
List<MyWhereCriteria> criteriaList = new LinkedList<>();
// 1. 组装主表数据对从表的过滤条件。
MyWhereCriteria inlistFilter = new MyWhereCriteria();
OnlineColumn masterColumn = masterTable.getColumnMap().get(relation.getMasterColumnId());
String masterColumnName = masterColumn.getColumnName();
Set<Object> masterIdSet = resultList.stream()
.map(r -> r.get(masterColumnName)).filter(Objects::nonNull).collect(Collectors.toSet());
inlistFilter.setCriteria(
slaveTableName, slaveColumnName, slaveColumn.getObjectFieldType(), MyWhereCriteria.OPERATOR_IN, masterIdSet);
criteriaList.add(inlistFilter);
// 2. 从表逻辑删除字段过滤。
if (relation.getSlaveTable().getLogicDeleteColumn() != null) {
MyWhereCriteria deleteFilter = new MyWhereCriteria();
deleteFilter.setCriteria(
slaveTableName,
relation.getSlaveTable().getLogicDeleteColumn().getColumnName(),
relation.getSlaveTable().getLogicDeleteColumn().getObjectFieldType(),
MyWhereCriteria.OPERATOR_EQUAL,
GlobalDeletedFlag.NORMAL);
criteriaList.add(deleteFilter);
}
if (StrUtil.isNotBlank(virtualColumn.getWhereClauseJson())) {
List<VirtualColumnWhereClause> whereClauseList =
JSONArray.parseArray(virtualColumn.getWhereClauseJson(), VirtualColumnWhereClause.class);
if (CollUtil.isNotEmpty(whereClauseList)) {
for (VirtualColumnWhereClause whereClause : whereClauseList) {
MyWhereCriteria whereClauseFilter = new MyWhereCriteria();
OnlineColumn c = relation.getSlaveTable().getColumnMap().get(whereClause.getColumnId());
whereClauseFilter.setCriteria(
slaveTableName,
c.getColumnName(),
c.getObjectFieldType(),
whereClause.getOperatorType(),
whereClause.getValue());
criteriaList.add(whereClauseFilter);
}
}
}
String criteriaString = MyWhereCriteria.makeCriteriaString(criteriaList);
List<Map<String, Object>> aggregationMapList =
onlineOperationMapper.getGroupedListByCondition(slaveTableName, selectList, criteriaString, groupBy);
this.doMakeAggregationData(resultList, aggregationMapList, masterColumnName, virtualColumn.getObjectFieldName());
}
private void doMakeAggregationData(
List<Map<String, Object>> resultList,
List<Map<String, Object>> aggregationMapList,
String masterColumnName,
String virtualColumnName) {
// 根据获取的分组聚合结果集,绑定到主表总的关联字段。
if (CollectionUtils.isEmpty(aggregationMapList)) {
return;
}
Map<Object, Object> relatedMap = new HashMap<>(aggregationMapList.size());
for (Map<String, Object> map : aggregationMapList) {
relatedMap.put(map.get(KEY_NAME), map.get(VALUE_NAME));
}
for (Map<String, Object> dataObject : resultList) {
Object masterIdValue = dataObject.get(masterColumnName);
if (masterIdValue != null) {
Object value = relatedMap.get(masterIdValue);
if (value != null) {
dataObject.put(virtualColumnName, value);
}
}
}
}
private Tuple2<String, String> makeSelectListAndGroupByClause(
String groupTableName,
String groupColumnName,
String aggregationTableName,
String aggregationColumnName,
Integer aggregationType) {
String aggregationFunc = AggregationType.getAggregationFunction(aggregationType);
// 构建Select List
// 如r_table.master_id groupedKey, SUM(r_table.aggr_column) aggregated_value
StringBuilder groupedSelectList = new StringBuilder(128);
groupedSelectList.append(groupTableName)
.append(".")
.append(groupColumnName)
.append(" ")
.append(KEY_NAME)
.append(", ")
.append(aggregationFunc)
.append("(")
.append(aggregationTableName)
.append(".")
.append(aggregationColumnName)
.append(") ")
.append(VALUE_NAME)
.append(" ");
StringBuilder groupBy = new StringBuilder(64);
groupBy.append(groupTableName).append(".").append(groupColumnName);
return new Tuple2<>(groupedSelectList.toString(), groupBy.toString());
}
private void buildDataListWithDict(
List<Map<String, Object>> resultList, OnlineTable slaveTable, String relationVariableName) {
if (CollUtil.isEmpty(resultList)) {
return;
}
Set<Long> dictIdSet = new HashSet<>();
// 先找主表字段对字典的依赖。
Multimap<Long, String> dictColumnMap = LinkedHashMultimap.create();
for (OnlineColumn column : slaveTable.getColumnMap().values()) {
if (column.getDictId() != null) {
dictIdSet.add(column.getDictId());
dictColumnMap.put(column.getDictId(),
relationVariableName + OnlineConstant.RELATION_TABLE_COLUMN_SEPARATOR + column.getColumnName());
}
}
this.doBuildDataListWithDict(resultList, dictIdSet, dictColumnMap);
}
private void buildDataListWithDict(
List<Map<String, Object>> resultList, OnlineTable masterTable, List<OnlineDatasourceRelation> relationList) {
if (CollUtil.isEmpty(resultList)) {
return;
}
Set<Long> dictIdSet = new HashSet<>();
// 先找主表字段对字典的依赖。
Multimap<Long, String> dictColumnMap = LinkedHashMultimap.create();
for (OnlineColumn column : masterTable.getColumnMap().values()) {
if (column.getDictId() != null) {
dictIdSet.add(column.getDictId());
dictColumnMap.put(column.getDictId(), column.getColumnName());
}
}
// 再找关联表字段对字典的依赖。
if (CollUtil.isNotEmpty(relationList)) {
for (OnlineDatasourceRelation relation : relationList) {
for (OnlineColumn column : relation.getSlaveTable().getColumnMap().values()) {
if (column.getDictId() != null) {
dictIdSet.add(column.getDictId());
dictColumnMap.put(column.getDictId(),
relation.getVariableName() + OnlineConstant.RELATION_TABLE_COLUMN_SEPARATOR + column.getColumnName());
}
}
}
}
this.doBuildDataListWithDict(resultList, dictIdSet, dictColumnMap);
}
private void doBuildDataListWithDict(
List<Map<String, Object>> resultList, Set<Long> dictIdSet, Multimap<Long, String> dictColumnMap) {
if (CollUtil.isEmpty(dictIdSet)) {
return;
}
List<OnlineDict> dictList = onlineDictService.getOnlineDictList(dictIdSet)
.stream().filter(d -> d.getDictType() == DictType.TABLE).collect(Collectors.toList());
for (OnlineDict dict : dictList) {
Collection<String> columnNameList = dictColumnMap.get(dict.getDictId());
for (String columnName : columnNameList) {
Set<Object> dictIdDataSet = new HashSet<>();
for (Map<String, Object> result : resultList) {
Object dictIdData = result.get(columnName);
if (ObjectUtil.isNotEmpty(dictIdData)) {
dictIdDataSet.add(dictIdData);
}
}
if (CollUtil.isEmpty(dictIdDataSet)) {
continue;
}
String selectFields = this.makeDictSelectFields(dict, true);
List<OnlineFilterDto> filterList = new LinkedList<>();
if (StrUtil.isNotBlank(dict.getDeletedColumnName())) {
OnlineFilterDto filter = new OnlineFilterDto();
filter.setColumnName(dict.getDeletedColumnName());
filter.setColumnValue(GlobalDeletedFlag.NORMAL);
filterList.add(filter);
}
OnlineFilterDto inlistFilter = new OnlineFilterDto();
inlistFilter.setColumnName(dict.getKeyColumnName());
inlistFilter.setColumnValueList(dictIdDataSet);
inlistFilter.setFilterType(FieldFilterType.IN_LIST_FILTER);
filterList.add(inlistFilter);
List<Map<String, Object>> dictResultList =
onlineOperationMapper.getDictList(dict.getTableName(), selectFields, filterList, null);
if (CollUtil.isEmpty(dictResultList)) {
continue;
}
Map<Object, Object> dictResultMap = new HashMap<>(dictResultList.size());
for (Map<String, Object> dictResult : dictResultList) {
dictResultMap.put(dictResult.get("id"), dictResult.get("name"));
}
String dictKeyName = columnName + "__DictMap";
for (Map<String, Object> result : resultList) {
Object dictIdData = result.get(columnName);
Object dictNameData = dictResultMap.get(dictIdData);
Map<String, Object> dictMap = new HashMap<>(2);
dictMap.put("id", dictIdData);
dictMap.put("name", dictNameData);
result.put(dictKeyName, dictMap);
}
}
}
}
private List<JoinTableInfo> makeJoinInfoList(
OnlineTable masterTable, List<OnlineDatasourceRelation> relationList) {
if (CollUtil.isEmpty(relationList)) {
return null;
}
Map<Long, OnlineColumn> masterTableColumnMap = masterTable.getColumnMap();
List<JoinTableInfo> joinInfoList = new LinkedList<>();
for (OnlineDatasourceRelation relation : relationList) {
JoinTableInfo joinInfo = new JoinTableInfo();
joinInfo.setLeftJoin(relation.getLeftJoin());
joinInfo.setJoinTableName(relation.getSlaveTable().getTableName());
// 根据配置动态拼接JOIN的关联条件同时要考虑从表的逻辑删除过滤。
OnlineColumn masterColumn = masterTableColumnMap.get(relation.getMasterColumnId());
OnlineColumn slaveColumn = relation.getSlaveTable().getColumnMap().get(relation.getSlaveColumnId());
StringBuilder conditionBuilder = new StringBuilder(64);
conditionBuilder
.append(masterTable.getTableName())
.append(".")
.append(masterColumn.getColumnName())
.append(" = ")
.append(relation.getSlaveTable().getTableName())
.append(".")
.append(slaveColumn.getColumnName());
if (relation.getSlaveTable().getLogicDeleteColumn() != null) {
conditionBuilder
.append(" AND ")
.append(relation.getSlaveTable().getTableName())
.append(".")
.append(relation.getSlaveTable().getLogicDeleteColumn().getColumnName())
.append(" = ")
.append(GlobalDeletedFlag.NORMAL);
}
joinInfo.setJoinCondition(conditionBuilder.toString());
joinInfoList.add(joinInfo);
}
return joinInfoList;
}
private String makeSelectFields(OnlineTable slaveTable, String relationVariableName) {
StringBuilder selectFieldBuider = new StringBuilder(512);
// 拼装主表的select fields字段。
for (OnlineColumn column : slaveTable.getColumnMap().values()) {
OnlineColumn deletedColumn = slaveTable.getLogicDeleteColumn();
if (deletedColumn != null && StrUtil.equals(column.getColumnName(), deletedColumn.getColumnName())) {
continue;
}
if (this.castToInteger(column)) {
selectFieldBuider
.append("CAST(")
.append(slaveTable.getTableName())
.append(".")
.append(column.getColumnName())
.append(" AS SIGNED) ")
.append(relationVariableName)
.append(OnlineConstant.RELATION_TABLE_COLUMN_SEPARATOR)
.append(column.getColumnName())
.append(",");
} else {
selectFieldBuider
.append(slaveTable.getTableName())
.append(".")
.append(column.getColumnName())
.append(" ")
.append(relationVariableName)
.append(OnlineConstant.RELATION_TABLE_COLUMN_SEPARATOR)
.append(column.getColumnName())
.append(",");
}
}
return selectFieldBuider.substring(0, selectFieldBuider.length() - 1);
}
private String makeSelectFields(OnlineTable masterTable, List<OnlineDatasourceRelation> relationList) {
StringBuilder selectFieldBuider = new StringBuilder(512);
if (CollUtil.isNotEmpty(relationList)) {
for (OnlineDatasourceRelation relation : relationList) {
OnlineTable slaveTable = relation.getSlaveTable();
Collection<OnlineColumn> columnList = slaveTable.getColumnMap().values();
for (OnlineColumn column : columnList) {
OnlineColumn deletedColumn = slaveTable.getLogicDeleteColumn();
if (deletedColumn != null && StrUtil.equals(column.getColumnName(), deletedColumn.getColumnName())) {
continue;
}
if (this.castToInteger(column)) {
selectFieldBuider
.append("CAST(")
.append(slaveTable.getTableName())
.append(".")
.append(column.getColumnName())
.append(" AS SIGNED) ")
.append(relation.getVariableName())
.append(OnlineConstant.RELATION_TABLE_COLUMN_SEPARATOR)
.append(column.getColumnName())
.append(",");
} else {
selectFieldBuider
.append(slaveTable.getTableName())
.append(".")
.append(column.getColumnName())
.append(" ")
.append(relation.getVariableName())
.append(OnlineConstant.RELATION_TABLE_COLUMN_SEPARATOR)
.append(column.getColumnName())
.append(",");
}
}
}
}
// 拼装主表的select fields字段。
for (OnlineColumn column : masterTable.getColumnMap().values()) {
OnlineColumn deletedColumn = masterTable.getLogicDeleteColumn();
if (deletedColumn != null && StrUtil.equals(column.getColumnName(), deletedColumn.getColumnName())) {
continue;
}
if (this.castToInteger(column)) {
selectFieldBuider
.append("CAST(")
.append(masterTable.getTableName())
.append(".")
.append(column.getColumnName())
.append(" AS SIGNED) ")
.append(column.getColumnName())
.append(",");
} else {
selectFieldBuider
.append(masterTable.getTableName())
.append(".")
.append(column.getColumnName())
.append(",");
}
}
return selectFieldBuider.substring(0, selectFieldBuider.length() - 1);
}
private String makeDictSelectFields(OnlineDict onlineDict, boolean ignoreParentId) {
StringBuilder sb = new StringBuilder(128);
sb.append(onlineDict.getKeyColumnName()).append(" id, ");
sb.append(onlineDict.getValueColumnName()).append(" name");
if (!ignoreParentId && onlineDict.getTreeFlag()) {
sb.append(", ").append(onlineDict.getParentKeyColumnName()).append(" parentId");
}
return sb.toString();
}
private boolean castToInteger(OnlineColumn column) {
return "tinyint(1)".equals(column.getFullColumnType());
}
private String makeColumnNames(List<ColumnData> columnDataList) {
StringBuilder sb = new StringBuilder(512);
for (ColumnData columnData : columnDataList) {
if (columnData.getColumn().getAutoIncrement()) {
continue;
}
sb.append(columnData.getColumn().getColumnName()).append(",");
}
return sb.substring(0, sb.length() - 1);
}
private void makeupColumnValue(ColumnData columnData) {
if (columnData.getColumn().getAutoIncrement()) {
return;
}
if (columnData.getColumn().getPrimaryKey()) {
if (columnData.getColumnValue() == null) {
if ("Long".equals(columnData.getColumn().getObjectFieldType())) {
columnData.setColumnValue(idGenerator.nextLongId());
} else {
columnData.setColumnValue(idGenerator.nextStringId());
}
}
} else if (columnData.getColumn().getFieldKind() != null) {
switch (columnData.getColumn().getFieldKind()) {
case FieldKind.CREATE_TIME:
case FieldKind.UPDATE_TIME:
columnData.setColumnValue(new Date());
break;
case FieldKind.CREATE_USER_ID:
case FieldKind.UPDATE_USER_ID:
columnData.setColumnValue(TokenData.takeFromRequest().getUserId());
break;
case FieldKind.LOGIC_DELETE:
columnData.setColumnValue(GlobalDeletedFlag.NORMAL);
break;
default:
break;
}
}
}
private List<OnlineFilterDto> makeDefaultFilter(OnlineTable table, OnlineColumn column, String columnValue) {
List<OnlineFilterDto> filterList = new LinkedList<>();
OnlineFilterDto dataIdFilter = new OnlineFilterDto();
dataIdFilter.setTableName(table.getTableName());
dataIdFilter.setColumnName(column.getColumnName());
dataIdFilter.setColumnValue(onlineOperationHelper.convertToTypeValue(column, columnValue));
filterList.add(dataIdFilter);
if (table.getLogicDeleteColumn() != null) {
OnlineFilterDto filter = new OnlineFilterDto();
filter.setTableName(table.getTableName());
filter.setColumnName(table.getLogicDeleteColumn().getColumnName());
filter.setColumnValue(GlobalDeletedFlag.NORMAL);
filterList.add(filter);
}
return filterList;
}
private boolean doLogicDelete(
OnlineTable table, OnlineColumn filterColumn, String filterColumnValue, String dataPermFilter) {
List<ColumnData> updateColumnList = new LinkedList<>();
ColumnData logicDeleteColumnData = new ColumnData();
logicDeleteColumnData.setColumn(table.getLogicDeleteColumn());
logicDeleteColumnData.setColumnValue(GlobalDeletedFlag.DELETED);
updateColumnList.add(logicDeleteColumnData);
List<ColumnData> whereColumnList = new LinkedList<>();
ColumnData relationSlaveColumnData = new ColumnData();
relationSlaveColumnData.setColumn(filterColumn);
relationSlaveColumnData.setColumnValue(
onlineOperationHelper.convertToTypeValue(filterColumn, filterColumnValue));
whereColumnList.add(relationSlaveColumnData);
return onlineOperationMapper.update(
table.getTableName(), updateColumnList, whereColumnList, dataPermFilter) != 0;
}
private String buildDataPermFilter(String tableName, String deptFilterColumnName, String userFilterColumnName) {
if (!dataFilterProperties.getEnabledDataPermFilter()) {
return null;
}
return processDataPerm(tableName, deptFilterColumnName, userFilterColumnName);
}
private String buildDataPermFilter(OnlineTable table) {
if (!dataFilterProperties.getEnabledDataPermFilter()) {
return null;
}
String deptFilterColumnName = null;
String userFilterColumnName = null;
for (OnlineColumn column : table.getColumnMap().values()) {
if (column.getDeptFilter()) {
deptFilterColumnName = column.getColumnName();
}
if (column.getUserFilter()) {
userFilterColumnName = column.getColumnName();
}
}
return processDataPerm(table.getTableName(), deptFilterColumnName, userFilterColumnName);
}
private String processDataPerm(String tableName, String deptFilterColumnName, String userFilterColumnName) {
TokenData tokenData = TokenData.takeFromRequest();
if (Boolean.TRUE.equals(tokenData.getIsAdmin())) {
return null;
}
String dataPermSessionKey =
RedisKeyUtil.makeSessionDataPermIdKey(tokenData.getSessionId());
RBucket<String> bucket = redissonClient.getBucket(dataPermSessionKey);
String dataPermData = bucket.get();
if (StrUtil.isBlank(dataPermData)) {
throw new NoDataPermException("No Related DataPerm found.");
}
Map<Integer, String> dataPermMap = new HashMap<>(8);
for (Map.Entry<String, Object> entry : JSON.parseObject(dataPermData).entrySet()) {
dataPermMap.put(Integer.valueOf(entry.getKey()), entry.getValue().toString());
}
if (MapUtil.isEmpty(dataPermMap)) {
throw new NoDataPermException("No Related DataPerm found.");
}
if (dataPermMap.containsKey(DataPermRuleType.TYPE_ALL)) {
return null;
}
return doProcessDataPerm(tableName, deptFilterColumnName, userFilterColumnName, dataPermMap);
}
private String doProcessDataPerm(
String tableName, String deptFilterColumnName, String userFilterColumnName, Map<Integer, String> dataPermMap) {
List<String> criteriaList = new LinkedList<>();
for (Map.Entry<Integer, String> entry : dataPermMap.entrySet()) {
String filterClause = processDataPermRule(
tableName, deptFilterColumnName, userFilterColumnName, entry.getKey(), entry.getValue());
if (StrUtil.isNotBlank(filterClause)) {
criteriaList.add(filterClause);
}
}
if (CollUtil.isEmpty(criteriaList)) {
return null;
}
StringBuilder filterBuilder = new StringBuilder(128);
filterBuilder.append("(");
filterBuilder.append(CollUtil.join(criteriaList, " OR "));
filterBuilder.append(")");
return filterBuilder.toString();
}
private String processDataPermRule(
String tableName, String deptFilterColumnName, String userFilterColumnName, Integer ruleType, String deptIds) {
TokenData tokenData = TokenData.takeFromRequest();
StringBuilder filter = new StringBuilder(128);
if (ruleType == DataPermRuleType.TYPE_USER_ONLY) {
if (StrUtil.isNotBlank(userFilterColumnName)) {
if (dataFilterProperties.getAddTableNamePrefix()) {
filter.append(tableName).append(".");
}
filter.append(userFilterColumnName)
.append(" = ")
.append(tokenData.getUserId());
}
} else {
if (StrUtil.isNotBlank(deptFilterColumnName)) {
if (ruleType == DataPermRuleType.TYPE_DEPT_ONLY) {
if (dataFilterProperties.getAddTableNamePrefix()) {
filter.append(tableName).append(".");
}
filter.append(deptFilterColumnName)
.append(" = ")
.append(tokenData.getDeptId());
} else if (ruleType == DataPermRuleType.TYPE_DEPT_AND_CHILD_DEPT) {
filter.append(" EXISTS ")
.append("(SELECT 1 FROM ")
.append(dataFilterProperties.getDeptRelationTablePrefix())
.append("sys_dept_relation WHERE ")
.append(dataFilterProperties.getDeptRelationTablePrefix())
.append("sys_dept_relation.parent_dept_id = ")
.append(tokenData.getDeptId())
.append(" AND ");
if (dataFilterProperties.getAddTableNamePrefix()) {
filter.append(tableName).append(".");
}
filter.append(deptFilterColumnName)
.append(" = ")
.append(dataFilterProperties.getDeptRelationTablePrefix())
.append("sys_dept_relation.dept_id) ");
} else if (ruleType == DataPermRuleType.TYPE_MULTI_DEPT_AND_CHILD_DEPT) {
filter.append(" EXISTS ")
.append("(SELECT 1 FROM ")
.append(dataFilterProperties.getDeptRelationTablePrefix())
.append("sys_dept_relation WHERE ")
.append(dataFilterProperties.getDeptRelationTablePrefix())
.append("sys_dept_relation.parent_dept_id IN (")
.append(deptIds)
.append(") AND ");
if (dataFilterProperties.getAddTableNamePrefix()) {
filter.append(tableName).append(".");
}
filter.append(deptFilterColumnName)
.append(" = ")
.append(dataFilterProperties.getDeptRelationTablePrefix())
.append("sys_dept_relation.dept_id) ");
} else if (ruleType == DataPermRuleType.TYPE_CUSTOM_DEPT_LIST) {
if (dataFilterProperties.getAddTableNamePrefix()) {
filter.append(tableName).append(".");
}
filter.append(deptFilterColumnName)
.append(" IN (")
.append(deptIds)
.append(") ");
}
}
}
return filter.toString();
}
@Data
static class VirtualColumnWhereClause {
private Long tableId;
private Long columnId;
private Integer operatorType;
private Object value;
}
}

View File

@@ -0,0 +1,233 @@
package com.flow.demo.common.online.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.core.base.service.BaseService;
import com.flow.demo.common.core.object.MyRelationParam;
import com.flow.demo.common.core.util.MyModelUtil;
import com.flow.demo.common.online.service.OnlineDatasourceService;
import com.flow.demo.common.sequence.wrapper.IdGeneratorWrapper;
import com.flow.demo.common.online.dao.OnlinePageDatasourceMapper;
import com.flow.demo.common.online.dao.OnlinePageMapper;
import com.flow.demo.common.online.model.OnlinePage;
import com.flow.demo.common.online.model.OnlinePageDatasource;
import com.flow.demo.common.online.model.constant.PageStatus;
import com.flow.demo.common.online.service.OnlineFormService;
import com.flow.demo.common.online.service.OnlinePageService;
import com.github.pagehelper.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
/**
* 在线表单页面数据操作服务类。
*
* @author Jerry
* @date 2021-06-06
*/
@Slf4j
@Service("onlinePageService")
public class OnlinePageServiceImpl extends BaseService<OnlinePage, Long> implements OnlinePageService {
@Autowired
private OnlinePageMapper onlinePageMapper;
@Autowired
private OnlinePageDatasourceMapper onlinePageDatasourceMapper;
@Autowired
private OnlineFormService onlineFormService;
@Autowired
private OnlineDatasourceService onlineDatasourceService;
@Autowired
private IdGeneratorWrapper idGenerator;
/**
* 返回当前Service的主表Mapper对象。
*
* @return 主表Mapper对象。
*/
@Override
protected BaseDaoMapper<OnlinePage> mapper() {
return onlinePageMapper;
}
/**
* 保存新增对象。
*
* @param onlinePage 新增对象。
* @return 返回新增对象。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public OnlinePage saveNew(OnlinePage onlinePage) {
onlinePage.setPageId(idGenerator.nextLongId());
Date now = new Date();
onlinePage.setUpdateTime(now);
onlinePage.setCreateTime(now);
onlinePage.setPublished(false);
MyModelUtil.setDefaultValue(onlinePage, "status", PageStatus.BASIC);
onlinePageMapper.insert(onlinePage);
return onlinePage;
}
/**
* 更新数据对象。
*
* @param onlinePage 更新的对象。
* @param originalOnlinePage 原有数据对象。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(OnlinePage onlinePage, OnlinePage originalOnlinePage) {
onlinePage.setUpdateTime(new Date());
onlinePage.setCreateTime(originalOnlinePage.getCreateTime());
onlinePage.setPublished(originalOnlinePage.getPublished());
// 这里重点提示,在执行主表数据更新之前,如果有哪些字段不支持修改操作,请用原有数据对象字段替换当前数据字段。
UpdateWrapper<OnlinePage> uw = this.createUpdateQueryForNullValue(onlinePage, onlinePage.getPageId());
return onlinePageMapper.update(onlinePage, uw) == 1;
}
/**
* 更新页面对象的发布状态。
*
* @param pageId 页面对象Id。
* @param published 新的状态。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void updatePublished(Long pageId, Boolean published) {
OnlinePage onlinePage = new OnlinePage();
onlinePage.setPageId(pageId);
onlinePage.setPublished(published);
onlinePageMapper.updateById(onlinePage);
}
/**
* 删除指定数据,及其包含的表单和数据源等。
*
* @param pageId 主键Id。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean remove(Long pageId) {
if (onlinePageMapper.deleteById(pageId) == 0) {
return false;
}
// 开始删除关联表单。
onlineFormService.removeByPageId(pageId);
// 先获取出关联的表单和数据源。
OnlinePageDatasource pageDatasourceFilter = new OnlinePageDatasource();
pageDatasourceFilter.setPageId(pageId);
List<OnlinePageDatasource> pageDatasourceList =
onlinePageDatasourceMapper.selectList(new QueryWrapper<>(pageDatasourceFilter));
if (CollUtil.isNotEmpty(pageDatasourceList)) {
for (OnlinePageDatasource pageDatasource : pageDatasourceList) {
onlineDatasourceService.remove(pageDatasource.getDatasourceId());
}
}
return true;
}
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlinePageListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlinePage> getOnlinePageList(OnlinePage filter, String orderBy) {
return onlinePageMapper.getOnlinePageList(filter, orderBy);
}
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlinePageList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlinePage> getOnlinePageListWithRelation(OnlinePage filter, String orderBy) {
List<OnlinePage> resultList = onlinePageMapper.getOnlinePageList(filter, orderBy);
// 在缺省生成的代码中如果查询结果resultList不是Page对象说明没有分页那么就很可能是数据导出接口调用了当前方法。
// 为了避免一次性的大量数据关联,规避因此而造成的系统运行性能冲击,这里手动进行了分批次读取,开发者可按需修改该值。
int batchSize = resultList instanceof Page ? 0 : 1000;
this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
return resultList;
}
/**
* 批量添加多对多关联关系。
*
* @param onlinePageDatasourceList 多对多关联表对象集合。
* @param pageId 主表Id。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void addOnlinePageDatasourceList(List<OnlinePageDatasource> onlinePageDatasourceList, Long pageId) {
for (OnlinePageDatasource onlinePageDatasource : onlinePageDatasourceList) {
onlinePageDatasource.setPageId(pageId);
onlinePageDatasourceMapper.insert(onlinePageDatasource);
}
}
/**
* 获取中间表数据。
*
* @param pageId 主表Id。
* @param datasourceId 从表Id。
* @return 中间表对象。
*/
@Override
public OnlinePageDatasource getOnlinePageDatasource(Long pageId, Long datasourceId) {
OnlinePageDatasource filter = new OnlinePageDatasource();
filter.setPageId(pageId);
filter.setDatasourceId(datasourceId);
return onlinePageDatasourceMapper.selectOne(new QueryWrapper<>(filter));
}
@Override
public List<OnlinePageDatasource> getOnlinePageDatasourceListByPageId(Long pageId) {
OnlinePageDatasource filter = new OnlinePageDatasource();
filter.setPageId(pageId);
return onlinePageDatasourceMapper.selectList(new QueryWrapper<>(filter));
}
/**
* 根据数据源Id返回使用该数据源的OnlinePage对象。
*
* @param datasourceId 数据源Id。
* @return 使用该数据源的页面列表。
*/
@Override
public List<OnlinePage> getOnlinePageListByDatasourceId(Long datasourceId) {
return onlinePageMapper.getOnlinePageListByDatasourceId(datasourceId);
}
/**
* 移除单条多对多关系。
*
* @param pageId 主表Id。
* @param datasourceId 从表Id。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean removeOnlinePageDatasource(Long pageId, Long datasourceId) {
OnlinePageDatasource filter = new OnlinePageDatasource();
filter.setPageId(pageId);
filter.setDatasourceId(datasourceId);
return onlinePageDatasourceMapper.delete(new QueryWrapper<>(filter)) > 0;
}
}

View File

@@ -0,0 +1,181 @@
package com.flow.demo.common.online.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.core.base.service.BaseService;
import com.flow.demo.common.core.constant.GlobalDeletedFlag;
import com.flow.demo.common.core.object.MyRelationParam;
import com.flow.demo.common.core.util.MyModelUtil;
import com.flow.demo.common.sequence.wrapper.IdGeneratorWrapper;
import com.flow.demo.common.online.dao.OnlineColumnRuleMapper;
import com.flow.demo.common.online.dao.OnlineRuleMapper;
import com.flow.demo.common.online.model.OnlineColumnRule;
import com.flow.demo.common.online.model.OnlineRule;
import com.flow.demo.common.online.service.OnlineRuleService;
import com.github.pagehelper.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Set;
/**
* 验证规则数据操作服务类。
*
* @author Jerry
* @date 2021-06-06
*/
@Slf4j
@Service("onlineRuleService")
public class OnlineRuleServiceImpl extends BaseService<OnlineRule, Long> implements OnlineRuleService {
@Autowired
private OnlineRuleMapper onlineRuleMapper;
@Autowired
private OnlineColumnRuleMapper onlineColumnRuleMapper;
@Autowired
private IdGeneratorWrapper idGenerator;
/**
* 返回当前Service的主表Mapper对象。
*
* @return 主表Mapper对象。
*/
@Override
protected BaseDaoMapper<OnlineRule> mapper() {
return onlineRuleMapper;
}
/**
* 保存新增对象。
*
* @param onlineRule 新增对象。
* @return 返回新增对象。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public OnlineRule saveNew(OnlineRule onlineRule) {
onlineRule.setRuleId(idGenerator.nextLongId());
Date now = new Date();
onlineRule.setUpdateTime(now);
onlineRule.setCreateTime(now);
onlineRule.setDeletedFlag(GlobalDeletedFlag.NORMAL);
MyModelUtil.setDefaultValue(onlineRule, "pattern", "");
onlineRuleMapper.insert(onlineRule);
return onlineRule;
}
/**
* 更新数据对象。
*
* @param onlineRule 更新的对象。
* @param originalOnlineRule 原有数据对象。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(OnlineRule onlineRule, OnlineRule originalOnlineRule) {
onlineRule.setUpdateTime(new Date());
onlineRule.setCreateTime(originalOnlineRule.getCreateTime());
UpdateWrapper<OnlineRule> uw = this.createUpdateQueryForNullValue(onlineRule, onlineRule.getRuleId());
return onlineRuleMapper.update(onlineRule, uw) == 1;
}
/**
* 删除指定数据。
*
* @param ruleId 主键Id。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean remove(Long ruleId) {
if (onlineRuleMapper.deleteById(ruleId) == 0) {
return false;
}
// 开始删除多对多父表的关联
OnlineColumnRule onlineColumnRule = new OnlineColumnRule();
onlineColumnRule.setRuleId(ruleId);
onlineColumnRuleMapper.delete(new QueryWrapper<>(onlineColumnRule));
return true;
}
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineRuleListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineRule> getOnlineRuleList(OnlineRule filter, String orderBy) {
return onlineRuleMapper.getOnlineRuleList(filter, orderBy);
}
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineRuleList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineRule> getOnlineRuleListWithRelation(OnlineRule filter, String orderBy) {
List<OnlineRule> resultList = onlineRuleMapper.getOnlineRuleList(filter, orderBy);
// 在缺省生成的代码中如果查询结果resultList不是Page对象说明没有分页那么就很可能是数据导出接口调用了当前方法。
// 为了避免一次性的大量数据关联,规避因此而造成的系统运行性能冲击,这里手动进行了分批次读取,开发者可按需修改该值。
int batchSize = resultList instanceof Page ? 0 : 1000;
this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
return resultList;
}
/**
* 在多对多关系中当前Service的数据表为从表返回不与指定主表主键Id存在对多对关系的列表。
*
* @param columnId 主表主键Id。
* @param filter 从表的过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineRule> getNotInOnlineRuleListByColumnId(Long columnId, OnlineRule filter, String orderBy) {
List<OnlineRule> resultList =
onlineRuleMapper.getNotInOnlineRuleListByColumnId(columnId, filter, orderBy);
this.buildRelationForDataList(resultList, MyRelationParam.dictOnly());
return resultList;
}
/**
* 在多对多关系中当前Service的数据表为从表返回与指定主表主键Id存在对多对关系的列表。
*
* @param columnId 主表主键Id。
* @param filter 从表的过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineRule> getOnlineRuleListByColumnId(Long columnId, OnlineRule filter, String orderBy) {
List<OnlineRule> resultList =
onlineRuleMapper.getOnlineRuleListByColumnId(columnId, filter, orderBy);
this.buildRelationForDataList(resultList, MyRelationParam.dictOnly());
return resultList;
}
/**
* 返回指定字段Id列表关联的字段规则对象列表。
*
* @param columnIdSet 指定的字段Id列表。
* @return 关联的字段规则对象列表。
*/
@Override
public List<OnlineColumnRule> getOnlineColumnRuleListByColumnIds(Set<Long> columnIdSet) {
return onlineColumnRuleMapper.getOnlineColumnRuleListByColumnIds(columnIdSet);
}
}

View File

@@ -0,0 +1,236 @@
package com.flow.demo.common.online.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.core.base.service.BaseService;
import com.flow.demo.common.core.object.MyRelationParam;
import com.flow.demo.common.core.util.RedisKeyUtil;
import com.flow.demo.common.sequence.wrapper.IdGeneratorWrapper;
import com.flow.demo.common.online.dao.OnlineTableMapper;
import com.flow.demo.common.online.model.OnlineColumn;
import com.flow.demo.common.online.model.OnlineTable;
import com.flow.demo.common.online.model.constant.FieldKind;
import com.flow.demo.common.online.object.SqlTable;
import com.flow.demo.common.online.service.OnlineColumnService;
import com.flow.demo.common.online.service.OnlineTableService;
import com.github.pagehelper.Page;
import com.google.common.base.CaseFormat;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* 数据表数据操作服务类。
*
* @author Jerry
* @date 2021-06-06
*/
@Slf4j
@Service("onlineTableService")
public class OnlineTableServiceImpl extends BaseService<OnlineTable, Long> implements OnlineTableService {
@Autowired
private OnlineTableMapper onlineTableMapper;
@Autowired
private OnlineColumnService onlineColumnService;
@Autowired
private IdGeneratorWrapper idGenerator;
@Autowired
private RedissonClient redissonClient;
/**
* 在线对象表的缺省缓存时间(小时)。
*/
private static final int DEFAULT_CACHED_TABLE_HOURS = 168;
/**
* 返回当前Service的主表Mapper对象。
*
* @return 主表Mapper对象。
*/
@Override
protected BaseDaoMapper<OnlineTable> mapper() {
return onlineTableMapper;
}
/**
* 基于数据库表保存新增对象。
*
* @param sqlTable 数据库表对象。
* @return 返回新增对象。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public OnlineTable saveNewFromSqlTable(SqlTable sqlTable) {
OnlineTable onlineTable = new OnlineTable();
onlineTable.setDblinkId(sqlTable.getDblinkId());
onlineTable.setTableId(idGenerator.nextLongId());
onlineTable.setTableName(sqlTable.getTableName());
String modelName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, sqlTable.getTableName());
onlineTable.setModelName(modelName);
Date now = new Date();
onlineTable.setUpdateTime(now);
onlineTable.setCreateTime(now);
onlineTableMapper.insert(onlineTable);
List<OnlineColumn> columnList = onlineColumnService.saveNewList(sqlTable.getColumnList(), onlineTable.getTableId());
onlineTable.setColumnList(columnList);
return onlineTable;
}
/**
* 更新数据对象。
*
* @param onlineTable 更新的对象。
* @param originalOnlineTable 原有数据对象。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(OnlineTable onlineTable, OnlineTable originalOnlineTable) {
this.evictTableCache(onlineTable.getTableId());
onlineTable.setUpdateTime(new Date());
onlineTable.setCreateTime(originalOnlineTable.getCreateTime());
UpdateWrapper<OnlineTable> uw = this.createUpdateQueryForNullValue(onlineTable, onlineTable.getTableId());
return onlineTableMapper.update(onlineTable, uw) == 1;
}
/**
* 删除指定表及其关联的字段数据。
*
* @param tableId 主键Id。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean remove(Long tableId) {
if (onlineTableMapper.deleteById(tableId) == 0) {
return false;
}
this.evictTableCache(tableId);
onlineColumnService.removeByTableId(tableId);
return true;
}
/**
* 删除指定数据表Id集合中的表及其关联字段。
*
* @param tableIdSet 待删除的数据表Id集合。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void removeByTableIdSet(Set<Long> tableIdSet) {
tableIdSet.forEach(this::evictTableCache);
onlineTableMapper.delete(
new QueryWrapper<OnlineTable>().lambda().in(OnlineTable::getTableId, tableIdSet));
onlineColumnService.removeByTableIdSet(tableIdSet);
}
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineTableListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineTable> getOnlineTableList(OnlineTable filter, String orderBy) {
return onlineTableMapper.getOnlineTableList(filter, orderBy);
}
/**
* 获取指定在线表Id集合的对象列表。
*
* @param tableIdSet 主键Id集合。
* @return 指定的数据表对象列表。
*/
@Override
public List<OnlineTable> getOnlineTableList(Set<Long> tableIdSet) {
return onlineTableMapper.selectBatchIds(tableIdSet);
}
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineTableList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineTable> getOnlineTableListWithRelation(OnlineTable filter, String orderBy) {
List<OnlineTable> resultList = onlineTableMapper.getOnlineTableList(filter, orderBy);
// 在缺省生成的代码中如果查询结果resultList不是Page对象说明没有分页那么就很可能是数据导出接口调用了当前方法。
// 为了避免一次性的大量数据关联,规避因此而造成的系统运行性能冲击,这里手动进行了分批次读取,开发者可按需修改该值。
int batchSize = resultList instanceof Page ? 0 : 1000;
this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
return resultList;
}
/**
* 根据数据源Id获取该数据源及其关联所引用的数据表列表。
*
* @param datasourceId 指定的数据源Id。
* @return 该数据源及其关联所引用的数据表列表。
*/
@Override
public List<OnlineTable> getOnlineTableListByDatasourceId(Long datasourceId) {
return onlineTableMapper.getOnlineTableListByDatasourceId(datasourceId);
}
/**
* 从缓存中获取指定的表数据及其关联字段列表。优先从缓存中读取,如果不存在则从数据库中读取,并同步到缓存。
* 该接口方法仅仅用户在线表单的动态数据操作接口,而非在线表单的配置接口。
*
* @param tableId 表主键Id。
* @return 查询后的在线表对象。
*/
@Override
public OnlineTable getOnlineTableFromCache(Long tableId) {
String redisKey = RedisKeyUtil.makeOnlineTableKey(tableId);
RBucket<String> tableBucket = redissonClient.getBucket(redisKey);
if (tableBucket.isExists()) {
String tableInfo = tableBucket.get();
return JSON.parseObject(tableInfo, OnlineTable.class);
}
OnlineTable table = this.getByIdWithRelation(tableId, MyRelationParam.full());
if (table == null) {
return null;
}
for (OnlineColumn column : table.getColumnList()) {
if (column.getPrimaryKey()) {
table.setPrimaryKeyColumn(column);
continue;
}
if (ObjectUtil.equal(column.getFieldKind(), FieldKind.LOGIC_DELETE)) {
table.setLogicDeleteColumn(column);
}
}
Map<Long, OnlineColumn> columnMap =
table.getColumnList().stream().collect(Collectors.toMap(OnlineColumn::getColumnId, c -> c));
table.setColumnMap(columnMap);
table.setColumnList(null);
tableBucket.set(JSON.toJSONString(table));
tableBucket.expire(DEFAULT_CACHED_TABLE_HOURS, TimeUnit.HOURS);
return table;
}
private void evictTableCache(Long tableId) {
String tableIdKey = RedisKeyUtil.makeOnlineTableKey(tableId);
redissonClient.getBucket(tableIdKey).delete();
}
}

View File

@@ -0,0 +1,175 @@
package com.flow.demo.common.online.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.flow.demo.common.core.base.dao.BaseDaoMapper;
import com.flow.demo.common.core.object.CallResult;
import com.flow.demo.common.core.object.MyRelationParam;
import com.flow.demo.common.core.base.service.BaseService;
import com.flow.demo.common.online.dao.OnlineVirtualColumnMapper;
import com.flow.demo.common.online.model.OnlineDatasource;
import com.flow.demo.common.online.model.OnlineVirtualColumn;
import com.flow.demo.common.online.model.constant.VirtualType;
import com.flow.demo.common.online.service.OnlineColumnService;
import com.flow.demo.common.online.service.OnlineDatasourceRelationService;
import com.flow.demo.common.online.service.OnlineDatasourceService;
import com.flow.demo.common.online.service.OnlineVirtualColumnService;
import com.flow.demo.common.sequence.wrapper.IdGeneratorWrapper;
import com.github.pagehelper.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* 虚拟字段数据操作服务类。
*
* @author Jerry
* @date 2021-06-06
*/
@Slf4j
@Service("onlineVirtualColumnService")
public class OnlineVirtualColumnServiceImpl
extends BaseService<OnlineVirtualColumn, Long> implements OnlineVirtualColumnService {
@Autowired
private OnlineVirtualColumnMapper onlineVirtualColumnMapper;
@Autowired
private OnlineDatasourceService onlineDatasourceService;
@Autowired
private OnlineDatasourceRelationService onlineDatasourceRelationService;
@Autowired
private OnlineColumnService onlineColumnService;
@Autowired
private IdGeneratorWrapper idGenerator;
/**
* 返回当前Service的主表Mapper对象。
*
* @return 主表Mapper对象。
*/
@Override
protected BaseDaoMapper<OnlineVirtualColumn> mapper() {
return onlineVirtualColumnMapper;
}
/**
* 保存新增对象。
*
* @param virtualColumn 新增对象。
* @return 返回新增对象。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public OnlineVirtualColumn saveNew(OnlineVirtualColumn virtualColumn) {
virtualColumn.setVirtualColumnId(idGenerator.nextLongId());
if (virtualColumn.getVirtualType().equals(VirtualType.AGGREGATION)) {
OnlineDatasource datasource = onlineDatasourceService.getById(virtualColumn.getDatasourceId());
virtualColumn.setTableId(datasource.getMasterTableId());
}
onlineVirtualColumnMapper.insert(virtualColumn);
return virtualColumn;
}
/**
* 更新数据对象。
*
* @param virtualColumn 更新的对象。
* @param originalVirtualColumn 原有数据对象。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(OnlineVirtualColumn virtualColumn, OnlineVirtualColumn originalVirtualColumn) {
if (virtualColumn.getVirtualType().equals(VirtualType.AGGREGATION)) {
if (!virtualColumn.getDatasourceId().equals(originalVirtualColumn.getDatasourceId())) {
OnlineDatasource datasource = onlineDatasourceService.getById(virtualColumn.getDatasourceId());
virtualColumn.setTableId(datasource.getMasterTableId());
}
}
UpdateWrapper<OnlineVirtualColumn> uw =
this.createUpdateQueryForNullValue(virtualColumn, virtualColumn.getVirtualColumnId());
return onlineVirtualColumnMapper.update(virtualColumn, uw) == 1;
}
/**
* 删除指定数据。
*
* @param virtualColumnId 主键Id。
* @return 成功返回true否则false。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean remove(Long virtualColumnId) {
return onlineVirtualColumnMapper.deleteById(virtualColumnId) == 1;
}
/**
* 获取单表查询结果。由于没有关联数据查询,因此在仅仅获取单表数据的场景下,效率更高。
* 如果需要同时获取关联数据,请移步(getOnlineVirtualColumnListWithRelation)方法。
*
* @param filter 过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineVirtualColumn> getOnlineVirtualColumnList(OnlineVirtualColumn filter, String orderBy) {
return onlineVirtualColumnMapper.getOnlineVirtualColumnList(filter, orderBy);
}
/**
* 获取主表的查询结果,以及主表关联的字典数据和一对一从表数据,以及一对一从表的字典数据。
* 该查询会涉及到一对一从表的关联过滤,或一对多从表的嵌套关联过滤,因此性能不如单表过滤。
* 如果仅仅需要获取主表数据,请移步(getOnlineVirtualColumnList),以便获取更好的查询性能。
*
* @param filter 主表过滤对象。
* @param orderBy 排序参数。
* @return 查询结果集。
*/
@Override
public List<OnlineVirtualColumn> getOnlineVirtualColumnListWithRelation(OnlineVirtualColumn filter, String orderBy) {
List<OnlineVirtualColumn> resultList = onlineVirtualColumnMapper.getOnlineVirtualColumnList(filter, orderBy);
int batchSize = resultList instanceof Page ? 0 : 1000;
this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
return resultList;
}
/**
* 根据数据表的集合,查询关联的虚拟字段数据列表。
* @param tableIdSet 在线数据表Id集合。
* @return 关联的虚拟字段数据列表。
*/
@Override
public List<OnlineVirtualColumn> getOnlineVirtualColumnListByTableIds(Set<Long> tableIdSet) {
LambdaQueryWrapper<OnlineVirtualColumn> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(OnlineVirtualColumn::getTableId, tableIdSet);
return onlineVirtualColumnMapper.selectList(queryWrapper);
}
/**
* 根据最新对象和原有对象的数据对比,判断关联的字典数据和多对一主表数据是否都是合法数据。
*
* @param virtualColumn 最新数据对象。
* @param originalVirtualColumn 原有数据对象。
* @return 数据全部正确返回true否则false。
*/
@Override
public CallResult verifyRelatedData(OnlineVirtualColumn virtualColumn, OnlineVirtualColumn originalVirtualColumn) {
String errorMessageFormat = "数据验证失败,关联的%s并不存在请刷新后重试";
if (this.needToVerify(virtualColumn, originalVirtualColumn, OnlineVirtualColumn::getDatasourceId)
&& !onlineDatasourceService.existId(virtualColumn.getDatasourceId())) {
return CallResult.error(String.format(errorMessageFormat, "数据源Id"));
}
if (this.needToVerify(virtualColumn, originalVirtualColumn, OnlineVirtualColumn::getRelationId)
&& !onlineDatasourceRelationService.existId(virtualColumn.getRelationId())) {
return CallResult.error(String.format(errorMessageFormat, "数据源关联Id"));
}
if (this.needToVerify(virtualColumn, originalVirtualColumn, OnlineVirtualColumn::getAggregationColumnId)
&& !onlineColumnService.existId(virtualColumn.getAggregationColumnId())) {
return CallResult.error(String.format(errorMessageFormat, "聚合字段Id"));
}
return CallResult.ok();
}
}

View File

@@ -0,0 +1,15 @@
package com.flow.demo.common.online.util;
/**
* 在线表单使用的常量数据。。
*
* @author Jerry
* @date 2021-06-06
*/
public class OnlineConstant {
/**
* 数据源关联变量名和从表字段名之间的连接字符串。
*/
public static final String RELATION_TABLE_COLUMN_SEPARATOR = "__";
}

View File

@@ -0,0 +1,50 @@
package com.flow.demo.common.online.util;
import com.flow.demo.common.core.util.DataSourceResolver;
import com.flow.demo.common.online.model.OnlineDatasourceRelation;
import com.flow.demo.common.online.model.OnlineDblink;
import com.flow.demo.common.online.model.OnlineDict;
import com.flow.demo.common.online.model.OnlineTable;
import com.flow.demo.common.online.service.OnlineDblinkService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.Serializable;
/**
* 目前仅仅应用于在线表单服务对象的多数据源切换的动态解析。
*
* @author Jerry
* @date 2021-06-06
*/
@Component
public class OnlineDataSourceResolver implements DataSourceResolver {
@Autowired
private OnlineDblinkService onlineDblinkService;
/**
* 动态解析方法。
* 先判断第一个参数的类型在根据具体的类型去获取dblinkId并根据该值进行多数据源的切换。
*
* @param arg 可选的入参。MyDataSourceResolver注解中的arg参数。
* @param methodArgs 被织入方法的所有参数。
* @return 返回用于多数据源切换的类型值。DataSourceResolveAspect 切面方法会根据该返回值和配置信息,进行多数据源切换。
*/
@Override
public int resolve(String arg, Object[] methodArgs) {
Serializable id;
if (methodArgs[0] instanceof OnlineTable) {
id = ((OnlineTable) methodArgs[0]).getDblinkId();
} else if (methodArgs[0] instanceof OnlineDict) {
id = ((OnlineDict) methodArgs[0]).getDblinkId();
} else if (methodArgs[0] instanceof OnlineDatasourceRelation) {
id = ((OnlineDatasourceRelation) methodArgs[0]).getSlaveTable().getDblinkId();
} else {
throw new IllegalArgumentException("动态表单操作服务方法,不支持类型 ["
+ methodArgs[0].getClass().getSimpleName() + "] 作为第一个参数!");
}
OnlineDblink dblink = onlineDblinkService.getById(id);
return dblink.getDblinkConfigConstant();
}
}

View File

@@ -0,0 +1,388 @@
package com.flow.demo.common.online.util;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.flow.demo.common.core.constant.ErrorCodeEnum;
import com.flow.demo.common.core.object.ResponseResult;
import com.flow.demo.common.core.upload.BaseUpDownloader;
import com.flow.demo.common.core.upload.UpDownloaderFactory;
import com.flow.demo.common.core.upload.UploadResponseInfo;
import com.flow.demo.common.core.upload.UploadStoreTypeEnum;
import com.flow.demo.common.online.config.OnlineProperties;
import com.flow.demo.common.online.model.OnlineColumn;
import com.flow.demo.common.online.model.OnlineDatasource;
import com.flow.demo.common.online.model.OnlineDatasourceRelation;
import com.flow.demo.common.online.model.OnlineTable;
import com.flow.demo.common.online.model.constant.FieldKind;
import com.flow.demo.common.online.model.constant.RelationType;
import com.flow.demo.common.online.object.ColumnData;
import com.flow.demo.common.online.service.OnlineDatasourceRelationService;
import com.flow.demo.common.online.service.OnlineDatasourceService;
import com.flow.demo.common.online.service.OnlineOperationService;
import com.flow.demo.common.online.service.OnlineTableService;
import com.flow.demo.common.redis.cache.SessionCacheHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;
/**
* 在线表单操作的通用帮助对象。
*
* @author Jerry
* @date 2021-06-06
*/
@Slf4j
@Component
public class OnlineOperationHelper {
@Autowired
private OnlineDatasourceService onlineDatasourceService;
@Autowired
private OnlineDatasourceRelationService onlineDatasourceRelationService;
@Autowired
private OnlineTableService onlineTableService;
@Autowired
private OnlineOperationService onlineOperationService;
@Autowired
private OnlineProperties onlineProperties;
@Autowired
private UpDownloaderFactory upDownloaderFactory;
@Autowired
private SessionCacheHelper cacheHelper;
/**
* 验证并获取数据源数据。
*
* @param datasourceId 数据源Id。
* @return 数据源详情数据。
*/
public ResponseResult<OnlineDatasource> verifyAndGetDatasource(Long datasourceId) {
String errorMessage;
OnlineDatasource datasource = onlineDatasourceService.getById(datasourceId);
if (datasource == null) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
OnlineTable masterTable = onlineTableService.getOnlineTableFromCache(datasource.getMasterTableId());
if (masterTable == null) {
errorMessage = "数据验证失败数据源主表Id不存在";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
datasource.setMasterTable(masterTable);
return ResponseResult.success(datasource);
}
/**
* 验证并获取数据源的关联数据。
*
* @param datasourceId 数据源Id。
* @param relationId 数据源关联Id。
* @return 数据源的关联详情数据。
*/
public ResponseResult<OnlineDatasourceRelation> verifyAndGetRelation(Long datasourceId, Long relationId) {
String errorMessage;
OnlineDatasourceRelation relation = onlineDatasourceRelationService.getById(relationId);
if (relation == null || !relation.getDatasourceId().equals(datasourceId)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
OnlineTable slaveTable = onlineTableService.getOnlineTableFromCache(relation.getSlaveTableId());
if (slaveTable == null) {
errorMessage = "数据验证失败,数据源关联 [" + relation.getRelationName() + " ] 引用的从表不存在!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
relation.setSlaveTable(slaveTable);
return ResponseResult.success(relation);
}
/**
* 验证并获取数据源的一对多关联数据。
*
* @param datasourceId 数据源Id。
* @param relationId 数据源一对多关联Id。
* @return 数据源的一对多关联详情数据。
*/
public ResponseResult<OnlineDatasourceRelation> verifyAndGetOneToManyRelation(Long datasourceId, Long relationId) {
String errorMessage;
OnlineDatasourceRelation relation = onlineDatasourceRelationService.getById(relationId);
if (relation == null || !relation.getDatasourceId().equals(datasourceId)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
if (!relation.getRelationType().equals(RelationType.ONE_TO_MANY)) {
errorMessage = "数据验证失败,数据源关联 [" + relation.getRelationName() + " ] 不是一对多关联,不能调用该接口!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
OnlineTable slaveTable = onlineTableService.getOnlineTableFromCache(relation.getSlaveTableId());
if (slaveTable == null) {
errorMessage = "数据验证失败,数据源关联 [" + relation.getRelationName() + " ] 引用的从表不存在!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
relation.setSlaveTable(slaveTable);
relation.setSlaveColumn(slaveTable.getColumnMap().get(relation.getSlaveColumnId()));
return ResponseResult.success(relation);
}
/**
* 验证并获取数据源的指定类型关联数据。
*
* @param datasourceId 数据源Id。
* @param relationType 数据源关联类型。
* @return 数据源指定关联类型的关联数据详情列表。
*/
public ResponseResult<List<OnlineDatasourceRelation>> verifyAndGetRelationList(
Long datasourceId, Integer relationType) {
String errorMessage;
Set<Long> datasourceIdSet = CollUtil.newHashSet(datasourceId);
List<OnlineDatasourceRelation> relationList = onlineDatasourceRelationService
.getOnlineDatasourceRelationListByDatasourceIds(datasourceIdSet, relationType);
for (OnlineDatasourceRelation relation : relationList) {
OnlineTable slaveTable = onlineTableService.getOnlineTableFromCache(relation.getSlaveTableId());
if (slaveTable == null) {
errorMessage = "数据验证失败,数据源关联 [" + relation.getRelationName() + "] 的从表Id不存在";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
relation.setSlaveTable(slaveTable);
}
return ResponseResult.success(relationList);
}
/**
* 构建在线表的数据记录。
*
* @param table 在线数据表对象。
* @param tableData 在线数据表数据。
* @param forUpdate 是否为更新。
* @param ignoreSetColumnId 忽略设置的字段Id。
* @return 在线表的数据记录。
*/
public ResponseResult<List<ColumnData>> buildTableData(
OnlineTable table, JSONObject tableData, boolean forUpdate, Long ignoreSetColumnId) {
List<ColumnData> columnDataList = new LinkedList<>();
String errorMessage;
for (OnlineColumn column : table.getColumnMap().values()) {
// 判断一下是否为需要自动填入的字段,如果是,这里就都暂时给空值了,后续操作会自动填补。
// 这里还能避免一次基于tableData的查询能快几纳秒也是好的。
if (this.isAutoSettingField(column) || ObjectUtil.equal(column.getColumnId(), ignoreSetColumnId)) {
columnDataList.add(new ColumnData(column, null));
continue;
}
Object value = tableData.get(column.getColumnName());
// 对于主键数据的处理。
if (column.getPrimaryKey()) {
// 如果是更新则必须包含主键参数。
if (forUpdate && value == null) {
errorMessage = "数据验证失败,数据表 ["
+ table.getTableName() + "] 主键字段 [" + column.getColumnName() + "] 不能为空值!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
} else {
if (value == null && !column.getNullable()) {
errorMessage = "数据验证失败,数据表 ["
+ table.getTableName() + "] 字段 [" + column.getColumnName() + "] 不能为空值!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
}
columnDataList.add(new ColumnData(column, value));
}
return ResponseResult.success(columnDataList);
}
/**
* 构建多个一对多从表的数据列表。
*
* @param datasourceId 数据源Id。
* @param slaveData 多个一对多从表数据的JSON对象。
* @return 构建后的多个一对多从表数据列表。
*/
public ResponseResult<Map<OnlineDatasourceRelation, List<List<ColumnData>>>> buildSlaveDataList(
Long datasourceId, JSONObject slaveData) {
Map<OnlineDatasourceRelation, List<List<ColumnData>>> relationDataMap = new HashMap<>(slaveData.size());
for (String key : slaveData.keySet()) {
Long relationId = Long.parseLong(key);
ResponseResult<OnlineDatasourceRelation> relationResult = this.verifyAndGetRelation(datasourceId, relationId);
if (!relationResult.isSuccess()) {
return ResponseResult.errorFrom(relationResult);
}
OnlineDatasourceRelation relation = relationResult.getData();
List<List<ColumnData>> relationDataList = new LinkedList<>();
relationDataMap.put(relation, relationDataList);
OnlineTable slaveTable = relation.getSlaveTable();
JSONArray slaveObjectArray = slaveData.getJSONArray(key);
for (int i = 0; i < slaveObjectArray.size(); i++) {
JSONObject slaveObject = slaveObjectArray.getJSONObject(i);
ResponseResult<List<ColumnData>> slaveColumnDataListResult =
this.buildTableData(slaveTable, slaveObject, false, relation.getSlaveColumnId());
if (!slaveColumnDataListResult.isSuccess()) {
return ResponseResult.errorFrom(slaveColumnDataListResult);
}
relationDataList.add(slaveColumnDataListResult.getData());
}
}
return ResponseResult.success(relationDataMap);
}
/**
* 将字符型字段值转换为与参数字段类型匹配的字段值。
*
* @param column 在线表单字段。
* @param dataId 字符型字段值。
* @return 转换后与参数字段类型匹配的字段值。
*/
public Object convertToTypeValue(OnlineColumn column, String dataId) {
if ("Long".equals(column.getObjectFieldType())) {
return Long.valueOf(dataId);
} else if ("Integer".equals(column.getObjectFieldType())) {
return Integer.valueOf(dataId);
}
return dataId;
}
/**
* 将字符型字段值集合转换为与参数字段类型匹配的字段值集合。
*
* @param column 在线表单字段。
* @param dataIdSet 字符型字段值集合。
* @return 转换后与参数字段类型匹配的字段值集合。
*/
public Set<?> convertToTypeValue(OnlineColumn column, Set<String> dataIdSet) {
if ("Long".equals(column.getObjectFieldType())) {
return dataIdSet.stream().map(Long::valueOf).collect(Collectors.toSet());
} else if ("Integer".equals(column.getObjectFieldType())) {
return dataIdSet.stream().map(Integer::valueOf).collect(Collectors.toSet());
}
return dataIdSet;
}
/**
* 下载数据。
*
* @param table 在线表对象。
* @param dataId 在线表数据主键Id。
* @param fieldName 数据表字段名。
* @param filename 下载文件名。
* @param asImage 是否为图片。
* @param response HTTP 应对对象。
*/
public void doDownload(
OnlineTable table, String dataId, String fieldName, String filename, Boolean asImage, HttpServletResponse response) {
// 使用try来捕获异常是为了保证一旦出现异常可以返回500的错误状态便于调试。
// 否则有可能给前端返回的是200的错误码。
try {
// 如果请求参数中没有包含主键Id就判断该文件是否为当前session上传的。
if (ObjectUtil.isEmpty(dataId)) {
if (!cacheHelper.existSessionUploadFile(filename)) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN);
return;
}
} else {
Map<String, Object> dataMap =
onlineOperationService.getMasterData(table, null, null, dataId);
if (dataMap == null) {
ResponseResult.output(HttpServletResponse.SC_NOT_FOUND);
return;
}
String fieldJsonData = (String) dataMap.get(fieldName);
if (fieldJsonData == null) {
ResponseResult.output(HttpServletResponse.SC_BAD_REQUEST);
return;
}
if (!BaseUpDownloader.containFile(fieldJsonData, filename)) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN);
return;
}
}
OnlineColumn downloadColumn = null;
for (OnlineColumn column : table.getColumnMap().values()) {
if (column.getColumnName().equals(fieldName)) {
if (asImage) {
if (ObjectUtil.notEqual(column.getFieldKind(), FieldKind.UPLOAD_IMAGE)) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FIELD));
return;
}
} else {
if (ObjectUtil.notEqual(column.getFieldKind(), FieldKind.UPLOAD)) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FIELD));
return;
}
}
downloadColumn = column;
break;
}
}
if (downloadColumn == null) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
ResponseResult.error(ErrorCodeEnum.INVALID_DATA_FIELD));
return;
}
BaseUpDownloader upDownloader = upDownloaderFactory.get(UploadStoreTypeEnum.LOCAL_SYSTEM);
upDownloader.doDownload(onlineProperties.getUploadFileBaseDir(),
table.getModelName(), fieldName, filename, asImage, response);
} catch (Exception e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
log.error(e.getMessage(), e);
}
}
/**
* 上传数据。
*
* @param table 在线表对象。
* @param fieldName 数据表字段名。
* @param asImage 是否为图片。
* @param uploadFile 上传的文件。
*/
public void doUpload(OnlineTable table, String fieldName, Boolean asImage, MultipartFile uploadFile) throws Exception {
OnlineColumn uploadColumn = null;
for (OnlineColumn column : table.getColumnMap().values()) {
if (column.getColumnName().equals(fieldName)) {
if (asImage) {
if (ObjectUtil.notEqual(column.getFieldKind(), FieldKind.UPLOAD_IMAGE)) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FIELD));
return;
}
} else {
if (ObjectUtil.notEqual(column.getFieldKind(), FieldKind.UPLOAD)) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FIELD));
return;
}
}
uploadColumn = column;
break;
}
}
if (uploadColumn == null) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
ResponseResult.error(ErrorCodeEnum.INVALID_DATA_FIELD));
return;
}
BaseUpDownloader upDownloader = upDownloaderFactory.get(UploadStoreTypeEnum.LOCAL_SYSTEM);
UploadResponseInfo responseInfo = upDownloader.doUpload(null,
onlineProperties.getUploadFileBaseDir(), table.getModelName(), fieldName, asImage, uploadFile);
if (responseInfo.getUploadFailed()) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
ResponseResult.error(ErrorCodeEnum.UPLOAD_FAILED, responseInfo.getErrorMessage()));
return;
}
// 动态表单的下载url和普通表单有所不同由前端负责动态拼接。
responseInfo.setDownloadUri(null);
cacheHelper.putSessionUploadFile(responseInfo.getFilename());
ResponseResult.output(ResponseResult.success(responseInfo));
}
private boolean isAutoSettingField(OnlineColumn column) {
return (ObjectUtil.equal(column.getFieldKind(), FieldKind.CREATE_TIME)
|| ObjectUtil.equal(column.getFieldKind(), FieldKind.CREATE_USER_ID)
|| ObjectUtil.equal(column.getFieldKind(), FieldKind.UPDATE_TIME)
|| ObjectUtil.equal(column.getFieldKind(), FieldKind.UPDATE_USER_ID)
|| ObjectUtil.equal(column.getFieldKind(), FieldKind.LOGIC_DELETE));
}
}

View File

@@ -0,0 +1,30 @@
package com.flow.demo.common.online.util;
/**
* 在线表单的工具类。
*
* @author Jerry
* @date 2021-06-06
*/
public class OnlineUtil {
/**
* 根据输入参数,拼接在线表单操作的查看权限字。
*
* @param datasourceVariableName 数据源变量名。
* @return 拼接后的在线表单操作的查看权限字。
*/
public static String makeViewPermCode(String datasourceVariableName) {
return "online:" + datasourceVariableName + ":view";
}
/**
* 根据输入参数,拼接在线表单操作的编辑权限字。
*
* @param datasourceVariableName 数据源变量名。
* @return 拼接后的在线表单操作的编辑权限字。
*/
public static String makeEditPermCode(String datasourceVariableName) {
return "online:" + datasourceVariableName + ":edit";
}
}

Some files were not shown because too many files have changed in this diff Show More