提交 1e9eb789 authored 作者: zhoushaopan's avatar zhoushaopan

[工作流模块] 增加了流程的变量池的结合

上级 c6fac988
package com.tykj.workflowcore.base.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
......@@ -24,10 +25,12 @@ public abstract class BaseEntity {
@ApiModelProperty("创建时间")
@Temporal(TemporalType.TIMESTAMP)
@JsonFormat(pattern = "yyyy-MM-dd hh:mm")
protected Date createdTime;
@ApiModelProperty("修改时间")
@Temporal(TemporalType.TIMESTAMP)
@JsonFormat(pattern = "yyyy-MM-dd hh:mm")
protected Date updatedTime;
@ApiModelProperty("逻辑删除 0为 false 1为 true")
......
package com.tykj.workflowcore.model_layer.config;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
* @Author WWW
* @Description
* @Date 10:47 2021/3/26
* @return
**/
@Configuration
@EnableCaching
public class MyCacheConfig {
@Bean
public CaffeineCacheManager cacheManager() {
/*
api + cache spring cache + hashmap
myCode + redis
spring cache + caffeine
SimpleCacheManager cacheManager = new SimpleCacheManager();
*/
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
Caffeine caffeine = Caffeine.newBuilder()
/* cache的初始容量值 */
.initialCapacity(150)
//maximumSize用来控制cache的最大缓存数量,maximumSize和maximumWeight(最大权重)不可以同时使用,
.maximumSize(1000)
//最后一次写入或者访问后过久过期
.expireAfterAccess(10, TimeUnit.SECONDS)
//创建或更新之后多久刷新,需要设置cacheLoader
.refreshAfterWrite(5, TimeUnit.SECONDS);
cacheManager.setCaffeine(caffeine);
cacheManager.setCacheLoader(cacheLoader());
/* 根据名字可以创建多个cache,但是多个cache使用相同的策略 */
cacheManager.setCacheNames(Arrays
.asList("tableInfos"));
//是否允许值为空
cacheManager.setAllowNullValues(false);
/* cacheManager.setCaches(Collections.singletonList(new ConcurrentMapCache("tableInfos"))); */
return cacheManager;
}
@Bean
public CacheLoader<Object, Object> cacheLoader() {
return new CacheLoader<Object, Object>() {
@Override
public Object load(Object key) {
return null;
}
// 重写这个方法将oldValue值返回回去,进而刷新缓存
@Override
public Object reload(Object key, Object oldValue) {
return oldValue;
}
};
}
}
//package com.tykj.workflowcore.model_layer.config;
//
//
//import com.github.benmanes.caffeine.cache.CacheLoader;
//import com.github.benmanes.caffeine.cache.Caffeine;
//import org.springframework.cache.CacheManager;
//import org.springframework.cache.annotation.EnableCaching;
//import org.springframework.cache.caffeine.CaffeineCacheManager;
//import org.springframework.cache.concurrent.ConcurrentMapCache;
//import org.springframework.cache.support.SimpleCacheManager;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//
//
//import java.util.Arrays;
//import java.util.Collections;
//import java.util.concurrent.TimeUnit;
//
//
///**
// * @Author WWW
// * @Description
// * @Date 10:47 2021/3/26
// * @return
// **/
//@Configuration
//@EnableCaching
//public class MyCacheConfig {
//
// @Bean
// public CacheManager cacheManager() {
// /*
// api + cache spring cache + hashmap
// myCode + redis
// spring cache + caffeine
// */
// SimpleCacheManager cacheManager = new SimpleCacheManager();
//
//// CaffeineCacheManager cacheManager = new CaffeineCacheManager();
//// Caffeine caffeine = Caffeine.newBuilder()
//// /* cache的初始容量值 */
//// .initialCapacity(150)
//// //maximumSize用来控制cache的最大缓存数量,maximumSize和maximumWeight(最大权重)不可以同时使用,
//// .maximumSize(1000);
//// //最后一次写入或者访问后过久过期
////// .expireAfterAccess(10, TimeUnit.SECONDS)
////// //创建或更新之后多久刷新,需要设置cacheLoader
////// .refreshAfterWrite(5, TimeUnit.SECONDS);
//// cacheManager.setCaffeine(caffeine);
//// cacheManager.setCacheLoader(cacheLoader());
//// /* 根据名字可以创建多个cache,但是多个cache使用相同的策略 */
//// cacheManager.setCacheNames(Arrays
//// .asList("tableInfos"));
//// //是否允许值为空
//// cacheManager.setAllowNullValues(false);
// cacheManager.setCaches(Collections.singletonList(new ConcurrentMapCache("tableInfos")));
// return cacheManager;
// }
//
//
// @Bean
// public CacheLoader<Object, Object> cacheLoader() {
// return new CacheLoader<Object, Object>() {
// @Override
// public Object load(Object key) {
// return null;
// }
// // 重写这个方法将oldValue值返回回去,进而刷新缓存
// @Override
// public Object reload(Object key, Object oldValue) {
// return oldValue;
// }
// };
// }
//}
......@@ -154,7 +154,7 @@ public class ModelController {
}
@ApiOperation("删除操作")
@DeleteMapping("/delete")
public ResponseEntity delTable(@RequestBody DelTableVO delTableVO) {
public ResponseEntity delTable( DelTableVO delTableVO) {
int i = modelService.delTable(delTableVO);
if (i==1){
......
......@@ -31,7 +31,7 @@ public interface ModelService {
* @return
* @throws SQLException
*/
@Cacheable(value = "tableInfos" )
// @Cacheable(cacheNames = "tableInfos")
Page<TableInfo> listAllEntities(SearchTableInfoVo searchTableInfoVo) throws SQLException;
......@@ -58,7 +58,7 @@ public interface ModelService {
* @param tableVO
* @return
*/
@CachePut(value = "tableInfos")
// @CachePut(cacheNames = "tableInfos")
TableVO newTable(TableVO tableVO);
/**
......@@ -97,7 +97,7 @@ public interface ModelService {
* @param updateTableInfoVO
* @return
*/
@CachePut(value = "tableInfos")
// @CachePut(cacheNames = "tableInfos")
int updateTable(UpdateTableInfoVO updateTableInfoVO);
......@@ -106,8 +106,8 @@ public interface ModelService {
* @param delTableVO
* @return
*/
@CacheEvict(value = "tableInfos")
@Transactional
// @CacheEvict(cacheNames = "tableInfos")
// @Transactional
int delTable(DelTableVO delTableVO);
......
......@@ -2,6 +2,7 @@ package com.tykj.workflowcore.workflow_editer.controller;
import com.tykj.workflowcore.base.result.ResultUtil;
import com.tykj.workflowcore.model_layer.entity.TableInfo;
import com.tykj.workflowcore.model_layer.entity.vo.TableAndColumnInfoVO;
import com.tykj.workflowcore.workflow_editer.entity.FormPage;
//import com.tykj.workflowcore.workflow_editer.entity.PageEntity;
import com.tykj.workflowcore.workflow_editer.service.FormPageService;
......@@ -68,7 +69,7 @@ public class FormPageController {
@ApiOperation("通过页面id查询所对应的数据模型")
@PostMapping("/findByPages")
public List<TableInfo> findByPages(@RequestBody List<Integer> pageIds){
public TableAndColumnInfoVO findByPages(@RequestBody List<Integer> pageIds){
return formPageService.findByPageIds(pageIds);
}
......
......@@ -75,7 +75,7 @@ public class WorkFlowController {
@ApiOperation("是否删除")
public ResponseEntity deleteFlow(Integer id){
workFlowService.deleteFlow(id);
return ResultUtil.success("该流程已被删除");
return ResultUtil.success("该流程删除成功");
}
@PostMapping("/flowProgress")
......
......@@ -57,7 +57,10 @@ public class ProcessEndListener extends AbstractFlowableEngineEventListener {
if (event.getEntity() instanceof ProcessInstance){
ProcessInstance processInstance = (ProcessInstance) event.getEntity();
String processDefinitionId = processInstance.getProcessDefinitionId();
String flowKey = processDefinitionId.substring(0,processDefinitionId.indexOf(":"));
String flowKey = processDefinitionId;
if (processDefinitionId.indexOf(":")>=0){
flowKey = processDefinitionId.substring(0,processDefinitionId.indexOf(":"));
}
List<VariableStorage> variableStorageList = variableStorageService.searchVariableStorageList(new SearchVariableStorageVo(flowKey));
for (VariableStorage variableStorage : variableStorageList) {
InvokeRequestVo variableInfo = variableStorage.getInvokeRequest();
......
package com.tykj.workflowcore.workflow_editer.service;
import com.tykj.workflowcore.model_layer.entity.TableInfo;
import com.tykj.workflowcore.model_layer.entity.vo.TableAndColumnInfoVO;
import com.tykj.workflowcore.workflow_editer.entity.FormPage;
import com.tykj.workflowcore.workflow_editer.entity.vo.FormPageVo;
import com.tykj.workflowcore.workflow_editer.entity.vo.PageFormPageVo;
......@@ -57,5 +58,5 @@ public interface FormPageService {
* @param pageIds 页面id
* @return
*/
List<TableInfo> findByPageIds(List<Integer> pageIds);
TableAndColumnInfoVO findByPageIds(List<Integer> pageIds);
}
......@@ -5,6 +5,8 @@ import com.github.wenhao.jpa.PredicateBuilder;
import com.github.wenhao.jpa.Specifications;
import com.tykj.workflowcore.model_layer.dao.TableInfoDao;
import com.tykj.workflowcore.model_layer.entity.TableInfo;
import com.tykj.workflowcore.model_layer.entity.vo.TableAndColumnInfoVO;
import com.tykj.workflowcore.model_layer.service.ModelService;
import com.tykj.workflowcore.workflow_editer.entity.FormPage;
import com.tykj.workflowcore.workflow_editer.dao.FormPageMapper;
import com.tykj.workflowcore.workflow_editer.service.FormPageService;
......@@ -35,7 +37,7 @@ public class FormPageServiceImpl implements FormPageService {
@Autowired
private FormPageMapper formPageMapper;
@Autowired
private TableInfoDao tableInfoDao;
private ModelService modelService;
@Override
public Integer savePage(@RequestBody FormPageVo inFormPageVo) {
inFormPageVo.setCreateTime(new Date());
......@@ -78,7 +80,7 @@ public class FormPageServiceImpl implements FormPageService {
}
@Override
public List<TableInfo> findByPageIds(List<Integer> pageIds) {
public TableAndColumnInfoVO findByPageIds(List<Integer> pageIds) {
ArrayList<TableInfo> list = new ArrayList<>();
PredicateBuilder<FormPage> builder = Specifications.and();
......@@ -93,8 +95,9 @@ public class FormPageServiceImpl implements FormPageService {
String[] split = entityIds.toString().split(",");
List<String> lastEntityIds = Arrays.asList(split).stream().distinct().collect(Collectors.toList());
//todo
Integer[] ids = (Integer[]) lastEntityIds.toArray();
return list;
return modelService.getTableInfoAndColumnInfoByBatch(ids);
}
}
......@@ -3,6 +3,7 @@ package com.tykj.workflowcore.workflow_editer.service.impl;
import com.tykj.workflowcore.api.service.SpringBeanService;
import com.tykj.workflowcore.base.result.ApiException;
import com.tykj.workflowcore.base.util.FileUtil;
import com.tykj.workflowcore.workflow_editer.util.MapUtils;
import com.tykj.workflowcore.workflow_editer.validate.ProcessValidatorFactoryExt;
import com.tykj.workflowcore.workflow_editer.entity.*;
import com.tykj.workflowcore.workflow_editer.dao.FlowsInfoMapper;
......@@ -13,6 +14,7 @@ import com.tykj.workflowcore.workflow_editer.service.UserService;
import com.tykj.workflowcore.workflow_editer.service.VariableStorageService;
import com.tykj.workflowcore.workflow_editer.service.WorkFlowService;
import com.tykj.workflowcore.workflow_editer.util.UserServiceBeanUtil;
import io.swagger.annotations.Api;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
......@@ -43,6 +45,7 @@ import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* ClassName: FlowableServiceImpl
......@@ -161,9 +164,9 @@ public class WorkFlowServiceImpl implements WorkFlowService {
String flowKey = flowsInfoVo.getFlowKey();
String fileXml = flowsInfoVo.getFileXml();
//生成xml文件
File file = FileUtil.createFileByString(basePath + flowKey + "bpmn20.xml",
flowsInfoVo.getFileXml().replaceAll("\\[\\?\\?[^\\]]+\\?\\?\\]", ""));
flowsInfoVo.getFileXml().replaceAll("\\[\\?\\?[^\\]]+\\?\\?\\]", "").replaceAll("&lt;","<").replaceAll("&gt;",">"));
FileUtil.createFileByString(basePath + flowKey + "bpmnCustom20.xml", flowsInfoVo.getFileXml());
FlowsInfo flowsInfo = new FlowsInfo();
......@@ -190,7 +193,7 @@ public class WorkFlowServiceImpl implements WorkFlowService {
for (int i =0;i<validate.size();i++){
ValidationError validationError = validate.get(i);
String problem = validationError.getProblem();
message.append(i+1+problem);
message.append(i+1+""+problem);
message.append("\r\n");
}
throw new ApiException(null,message.toString());
......@@ -205,6 +208,7 @@ public class WorkFlowServiceImpl implements WorkFlowService {
@Override
public Integer createFlow(FlowsInfo flowsInfo) {
flowsInfo.setCreatedTime(new Date());
FlowsInfo flowsInfo1 = flowsInfoMapper.save(flowsInfo);
return flowsInfo1.getId();
}
......@@ -251,8 +255,8 @@ public class WorkFlowServiceImpl implements WorkFlowService {
if (nextTaskVo.getRoleId() != null || nextTaskVo.getUserId() != null) {
taskQuery.or();
if (nextTaskVo.getUserId() != null) {
// taskQuery.taskCandidateUser(nextTaskVo.getUserId()).orderByTaskCreateTime().desc();
taskQuery.taskAssignee(nextTaskVo.getUserId()).orderByTaskCreateTime().desc();
taskQuery.taskCandidateUser(nextTaskVo.getUserId()).orderByTaskCreateTime().desc();
// taskQuery.taskAssignee(nextTaskVo.getUserId()).orderByTaskCreateTime().desc();
}
if (nextTaskVo.getRoleId() != null && nextTaskVo.getRoleId().size() > 0) {
taskQuery.taskCandidateGroupIn(nextTaskVo.getRoleId()).orderByTaskCreateTime().desc();
......@@ -301,27 +305,45 @@ public class WorkFlowServiceImpl implements WorkFlowService {
@Override
public void completeTask(@RequestBody TaskVo taskVo) {
Map<String, Object> map = new HashMap<>();
if (taskVo.getMap() != null) {
setVariables(taskVo.getMap());
}
// Map<String, Object> map = new HashMap<>();
// if (taskVo.getMap() != null) {
// map = setVariables(taskVo.getMap());
// }
ConcurrentHashMap flowMap = new ConcurrentHashMap<>();
ConcurrentHashMap oldFlowMap = new ConcurrentHashMap<>();
ConcurrentHashMap userMap = new ConcurrentHashMap<>();
Task task = taskService.createTaskQuery().taskId(taskVo.getTaskId()).singleResult();
if (task==null){
throw new ApiException(null,"该任务已经被完成了");
}
//用户map
userMap.putAll(taskVo.getMap());
//流程map
oldFlowMap.putAll(taskService.getVariables(taskVo.getTaskId()));
flowMap.putAll(taskService.getVariables(taskVo.getTaskId()));
MapUtils.loopMap(flowMap,"",userMap);
String processInstanceId = task.getProcessInstanceId();
//如果 存在任务评论的话 向任务中添加任务评论
if (taskVo.getComments() != null) {
taskService.addComment(task.getId(), processInstanceId, taskVo.getComments());
}
//先判断是不是表达式
if (taskVo.getConditionalExpression() != null) {
claimTask(task.getId(), userService.getCurrentUser().getId());
taskService.complete(task.getId());
//先判断是
if (taskVo.getHandlingOpinion() != null){
taskVo.getMap().put("handlingOpinion", taskVo.getHandlingOpinion());
}
try {
taskService.setVariables(task.getId(),flowMap);
taskService.complete(task.getId(), taskVo.getMap());
} catch (Exception e) {
taskService.removeVariables(task.getId(),taskService.getVariables(task.getId()).keySet());
taskService.setVariables(task.getId(),oldFlowMap);
} else {
map.put("handlingOpinion", taskVo.getHandlingOpinion());
claimTask(task.getId(), userService.getCurrentUser().getId());
taskService.complete(task.getId(), map);
}
}
@Override
......@@ -366,7 +388,7 @@ public class WorkFlowServiceImpl implements WorkFlowService {
Optional<FlowsInfo> flowsInfoMapperById = flowsInfoMapper.findById(id);
if (flowsInfoMapperById.isPresent()) {
FlowsInfo flowsInfo = flowsInfoMapperById.get();
if (flowsInfo.getState() == 0) {
if (flowsInfo.getDeleted() == 0) {
flowsInfoMapper.deleteById(id);
}
} else {
......@@ -426,7 +448,7 @@ public class WorkFlowServiceImpl implements WorkFlowService {
@Override
public List<Object> findHistoryTask(String userId) {
List<HistoricTaskInstance> taskInstanceList =
historyService.createHistoricTaskInstanceQuery().taskAssignee(userId).finished().list();
historyService.createHistoricTaskInstanceQuery().taskCandidateUser(userId).finished().list();
ArrayList<Object> arrayList = new ArrayList<>();
arrayList.addAll(taskInstanceList);
return arrayList;
......@@ -434,7 +456,12 @@ public class WorkFlowServiceImpl implements WorkFlowService {
@Override
public String getCurrentNodeId(String taskId) {
return taskService.createTaskQuery().taskId(taskId).singleResult().getTaskDefinitionKey();
if (taskId!=null){
return taskService.createTaskQuery().taskId(taskId).singleResult().getTaskDefinitionKey();
}else {
throw new ApiException(null,"任务已经不存在了");
}
}
@Override
......
package com.tykj.workflowcore.workflow_editer.util;
import org.springframework.util.StringUtils;
import java.util.Map;
import java.util.Set;
/**
* ClassName: MapUtils
* Package: com.tykj.workflowcore.workflow_editer.util
* Description:
* Datetime: 2021/3/30 16:15
*
* @Author: zsp
*/
public class MapUtils {
public static void loopMap(Map m1, String p, Map m2) {
m1.forEach((key, value) -> {
Set mapKeySetByPath = getMapKeySetByPath(m2, p + "." + key);
System.out.println(p + "." + key);
System.out.println(mapKeySetByPath);
if (mapKeySetByPath!=null){
mapKeySetByPath.forEach( (keyStr)->{
if (!m1.containsKey(keyStr)){
m1.put(keyStr,getMapByPath(m2,p + "." + keyStr));
}
});
}
if (value instanceof Map) {
String path;
if (StringUtils.isEmpty(p)) {
path = (String) key;
} else {
path = p + "." + key;
}
loopMap((Map) value, path, m2);
} else {
if (!StringUtils.isEmpty(p)) {
String path = p + "." + key;
Object result = getMapByPath(m2, path);
if (result != null) {
m1.put(key, result);
}
}
}
});
}
public static Object getMapByPath(Map m2, String path) {
int point = path.indexOf(".");
if (point==0){
//第一层
Object r = m2.get(path.substring(1));
return r;
}
if (point == -1) {
//已经递归到最后一层了
Object r = m2.get(path);
return r;
}
String key = path.substring(0, point);
String last = path.substring(point + 1);
Object result = m2.get(key);
if (result == null) {
return null;
} else {
try {
return getMapByPath((Map) result, last);
} catch (Exception e) {
return null;
}
}
}
public static Set getMapKeySetByPath(Map m2, String path) {
int point = path.indexOf(".");
if (point <= 0) {
Set r = m2.keySet();
return r;
}
String key = path.substring(0, point);
String last = path.substring(point + 1);
Object result = m2.get(key);
if (result == null) {
return null;
} else {
try {
return getMapKeySetByPath((Map) result, last);
} catch (Exception e) {
return null;
}
}
}
}
......@@ -15,6 +15,7 @@ import org.springframework.stereotype.Component;
*/
@Component
public class ProcessValidatorFactoryExt extends ProcessValidatorFactory {
@Override
public ProcessValidator createDefaultProcessValidator() {
ProcessValidator defaultProcessValidator = super.createDefaultProcessValidator();
......@@ -24,4 +25,5 @@ public class ProcessValidatorFactoryExt extends ProcessValidatorFactory {
defaultProcessValidator.getValidatorSets().add(validatorSet);
return defaultProcessValidator;
}
}
......@@ -27,8 +27,7 @@ public class UserTaskValidator extends ProcessLevelValidator {
List<EndEvent> endEvents = process.findFlowElementsOfType(EndEvent.class);
//判断开始节点
List<StartEvent> startEvents = process.findFlowElementsOfType(StartEvent.class);
//判断网关
// List<ExclusiveGateway> exclusiveGateways = process.findFlowElementsOfType(ExclusiveGateway.class);
if (userTaskList.size() > 0) {
for (UserTask userTask : userTaskList) {
if (userTask.getName() == null || userTask.getName().equals("")) {
......@@ -44,7 +43,8 @@ public class UserTaskValidator extends ProcessLevelValidator {
}
List<String> candidateUsers = userTask.getCandidateUsers();
List<String> candidateGroups = userTask.getCandidateGroups();
if (candidateUsers.size() == 0 || candidateUsers.equals("") && candidateGroups.size() == 0 || candidateGroups.equals("")) {
if ((candidateUsers.size() == 0 || candidateUsers.equals("")) && (candidateGroups.size() == 0 || candidateGroups.equals(""))) {
errors.add(createValidationErrorProblem("用户节点未设置用户或者未设置用户组"));
}
......@@ -72,19 +72,20 @@ public class UserTaskValidator extends ProcessLevelValidator {
}
}
}
// for (ExclusiveGateway exclusiveGateway : exclusiveGateways) {
// //输出流
// List<SequenceFlow> outgoingFlows = exclusiveGateway.getOutgoingFlows();
// if (outgoingFlows.size() == 0 || outgoingFlows.equals("")){
// validationError.setProblem(exclusiveGateway.getId()+"--->缺少连接用户任务的输出流");
// }
// //输入流
// List<SequenceFlow> incomingFlows = exclusiveGateway.getIncomingFlows();
// if (incomingFlows.size() == 0 || incomingFlows.equals("")){
// validationError.setProblem(exclusiveGateway.getId()+"--->缺少连接用户任务的输入流");
// }
// }
//判断网关
List<ExclusiveGateway> exclusiveGateways = process.findFlowElementsOfType(ExclusiveGateway.class);
for (ExclusiveGateway exclusiveGateway : exclusiveGateways) {
//输出流
List<SequenceFlow> outgoingFlows = exclusiveGateway.getOutgoingFlows();
if (outgoingFlows.size() == 0 || outgoingFlows.equals("")){
errors.add(createValidationErrorProblem("缺少连接网关的输入流"));
}
//输入流
List<SequenceFlow> incomingFlows = exclusiveGateway.getIncomingFlows();
if (incomingFlows.size() == 0 || incomingFlows.equals("")){
errors.add(createValidationErrorProblem("缺少连接网关的输出流"));
}
}
}
......
......@@ -2,7 +2,7 @@ spring:
datasource:
username: root
password: Huang123+
url: jdbc:mysql://47.106.142.73:3306/www2?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf-8&nullCatalogMeansCurrent=true
url: jdbc:mysql://47.106.142.73:3306/www?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf-8&nullCatalogMeansCurrent=true
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
show-sql: true
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论