优化:删除动态表单时对对原始数据库表自动进行备份,并增加事务

master
Guo XIn 1 year ago
parent 9aeb184fb4
commit 0c2fa9586d
  1. 2
      shandan-basedata/src/main/java/com/keyware/shandan/dynacmicform/controller/DynamicFormController.java
  2. 20
      shandan-basedata/src/main/java/com/keyware/shandan/dynacmicform/core/basic/services/DynamicDataService.java
  3. 35
      shandan-basedata/src/main/java/com/keyware/shandan/dynacmicform/core/basic/services/DynamicFormService.java
  4. 8
      shandan-basedata/src/main/java/com/keyware/shandan/dynacmicform/core/basic/services/impl/FormInfoServiceImpl.java
  5. 15
      shandan-basedata/src/main/java/com/keyware/shandan/dynacmicform/core/db/SqlHelper.java
  6. 56
      shandan-basedata/src/main/java/com/keyware/shandan/dynacmicform/core/db/executor/SqlExecutor.java
  7. 3
      shandan-control/src/main/java/com/keyware/shandan/control/config/DynamicFormListener.java

@ -157,7 +157,7 @@ public class DynamicFormController {
* @return 结果
*/
@PostMapping("/api/form/delete")
public Result<Object> deleteFormInfo(int id) {
public Result<Object> deleteFormInfo(int id) throws Exception {
return Result.of(dynamicFormService.delete(id));
}
}

@ -14,6 +14,12 @@ import java.util.*;
@Service
public class DynamicDataService {
private final SqlExecutor sqlExecutor;
public DynamicDataService(SqlExecutor sqlExecutor) {
this.sqlExecutor = sqlExecutor;
}
/**
* 根据ID删除数据
@ -25,7 +31,7 @@ public class DynamicDataService {
*/
public boolean deleteById(FormInfoPo form, Integer id) throws Exception {
QueryParam param = QueryParam.builder().column("ID").eq(id).build();
return SqlExecutor.executeUpdate(SqlHelper.deleteSql(form, param), id);
return sqlExecutor.executeUpdate(SqlHelper.deleteSql(form, param), id);
}
@ -58,7 +64,7 @@ public class DynamicDataService {
// 插入Sql,去除主键列
params.remove("ID");
LinkedHashMap<String, Object> data = new LinkedHashMap<>(params);
return SqlExecutor.executeUpdate(SqlHelper.insertSql(form, data), data.values().toArray());
return sqlExecutor.executeUpdate(SqlHelper.insertSql(form, data), data.values().toArray());
}
/**
@ -75,7 +81,7 @@ public class DynamicDataService {
QueryParam queryParam = QueryParam.builder().column("ID").eq(id).build();
List<Object> paramValues = new ArrayList<>(dataMap.values());
paramValues.addAll(queryParam.getParamValues());
return SqlExecutor.executeUpdate(SqlHelper.updateSql(form, dataMap, queryParam), paramValues.toArray());
return sqlExecutor.executeUpdate(SqlHelper.updateSql(form, dataMap, queryParam), paramValues.toArray());
}
/**
@ -88,7 +94,7 @@ public class DynamicDataService {
*/
public Map<String, Object> getById(FormInfoPo form, @NotNull Integer id) throws Exception {
QueryParam param = QueryParam.builder().column("ID").eq(id).build();
List<Map<String, Object>> list = SqlExecutor.executeQuery(SqlHelper.selectSql(form, param), id);
List<Map<String, Object>> list = sqlExecutor.executeQuery(SqlHelper.selectSql(form, param), id);
if (list == null) {
return null;
}
@ -105,12 +111,12 @@ public class DynamicDataService {
* @throws Exception -
*/
public Page<Map<String, Object>> pageList(FormInfoPo form, QueryParam params) throws Exception {
List<Map<String, Object>> countList = SqlExecutor.executeQuery(SqlHelper.countSql(form, params), params.getParamValues().toArray());
List<Map<String, Object>> countList = sqlExecutor.executeQuery(SqlHelper.countSql(form, params), params.getParamValues().toArray());
long count = 0;
if (countList != null && countList.size() > 0) {
count = (long) countList.get(0).get("COUNT");
}
List<Map<String, Object>> dataList = SqlExecutor.executeQuery(SqlHelper.pageSelectSql(form, params), params.getParamValues().toArray());
List<Map<String, Object>> dataList = sqlExecutor.executeQuery(SqlHelper.pageSelectSql(form, params), params.getParamValues().toArray());
Page<Map<String, Object>> page = new Page<>(params.getPage(), params.getPageSize(), count);
page.setRecords(dataList);
return page;
@ -124,6 +130,6 @@ public class DynamicDataService {
* @throws Exception
*/
public List<Map<String, Object>> list(FormInfoPo form) throws Exception {
return SqlExecutor.executeQuery(SqlHelper.selectSql(form, null));
return sqlExecutor.executeQuery(SqlHelper.selectSql(form, null));
}
}

@ -3,6 +3,7 @@ package com.keyware.shandan.dynacmicform.core.basic.services;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.keyware.shandan.common.util.DateUtil;
import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.dynacmicform.core.DynamicFormEventListener;
import com.keyware.shandan.dynacmicform.core.basic.entity.FormInfoPo;
@ -22,11 +23,14 @@ import java.util.List;
@Slf4j
@Service
public class DynamicFormService {
private final SqlExecutor sqlExecutor;
private final FormInfoService formInfoService;
private final DynamicFormEventListener dynamicFormEventListener;
public DynamicFormService(FormInfoService formInfoService, DynamicFormEventListener dynamicFormEventListener) {
public DynamicFormService(SqlExecutor sqlExecutor,
FormInfoService formInfoService,
DynamicFormEventListener dynamicFormEventListener) {
this.sqlExecutor = sqlExecutor;
this.formInfoService = formInfoService;
this.dynamicFormEventListener = dynamicFormEventListener;
}
@ -43,8 +47,8 @@ public class DynamicFormService {
FormInfoPo oldForm = formInfoService.getById(form.getId());
Table table = TableInfoParser.parseTable(form);
if (oldForm == null) {
String sql = SqlHelper.createSql(table);
SqlExecutor.execute(sql);
String sql = SqlHelper.tableCreateSql(table);
sqlExecutor.execute(sql);
} else {
Table oldTable = TableInfoParser.parseTable(oldForm);
List<String> alterSqlList = SqlHelper.alterTableDropColumnSql(oldTable, table);
@ -53,7 +57,7 @@ public class DynamicFormService {
alterSqlList.addAll(SqlHelper.alterTableAddColumnSql(oldTable, table));
alterSqlList.addAll(SqlHelper.commentTableSql(oldTable, table));
alterSqlList.addAll(SqlHelper.commentColumnSql(oldTable, table));
SqlExecutor.executeBatch(alterSqlList);
sqlExecutor.executeBatch(alterSqlList);
}
if (StringUtils.isBlank(form.getQueryConfig())) {
generateQueryConfig(form);
@ -67,19 +71,30 @@ public class DynamicFormService {
}
/**
* 删除表单信息
* 删除表单信息逻辑删除并对实际数据表进行重命名备份
*
* @param id
* @return
*/
@Transactional(rollbackFor = Exception.class)
public boolean delete(Integer id) {
public boolean delete(Integer id) throws Exception {
FormInfoPo form = formInfoService.getById(id);
if (form != null) {
// 对原始表结构进行重命名备份
Table table = TableInfoParser.parseTable(form);
String newName = table.getName() + "_BACKUP_" + DateUtil.getFormatNowDate("yyyyMMddHHmmss");
String sql = SqlHelper.tableRenameSql(table.getName(), newName);
sqlExecutor.execute(sql);
// 更新表名后进行逻辑删除
form.setFormId(newName);
formInfoService.updateById(form);
boolean ok = formInfoService.removeById(id);
if (ok) {
dynamicFormEventListener.onDrop(form);
if (!ok) {
throw new RuntimeException("表单信息删除异常");
}
return ok;
}
dynamicFormEventListener.onDrop(form);
return true;
}
/**

@ -5,6 +5,8 @@ import com.keyware.shandan.dynacmicform.core.basic.entity.FormInfoPo;
import com.keyware.shandan.dynacmicform.core.basic.mapper.FormInfoMapper;
import com.keyware.shandan.dynacmicform.core.basic.services.FormInfoService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable;
@ -15,4 +17,10 @@ public class FormInfoServiceImpl extends ServiceImpl<FormInfoMapper, FormInfoPo>
public boolean removeById(Serializable id) {
return super.removeById(id);
}
/*@Override
@Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
public boolean saveOrUpdate(FormInfoPo entity) {
return super.saveOrUpdate(entity);
}*/
}

@ -1,6 +1,7 @@
package com.keyware.shandan.dynacmicform.core.db;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.keyware.shandan.common.util.StreamUtil;
import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.dynacmicform.core.basic.entity.FormInfoPo;
@ -23,7 +24,7 @@ public class SqlHelper {
* @param table
* @return
*/
public static String createSql(Table table) {
public static String tableCreateSql(Table table) {
StringBuilder sqlBuilder = new StringBuilder("CREATE TABLE ");
sqlBuilder.append("\"").append(table.getName()).append("\" (");
@ -46,13 +47,17 @@ public class SqlHelper {
return sqlBuilder.toString();
}
public static String tableRenameSql(String oldTableName, String newTableName) {
return StrUtil.format("alter table \"{}\" rename to \"{}\"", oldTableName, newTableName);
}
/**
* 修改表的sql
*
* @param columns 修改的列集合
* @return
*/
public static List<String> alterSql(Map<String, List<Column>> columns) {
public static List<String> tableAlterSql(Map<String, List<Column>> columns) {
List<String> alterSqlList = new ArrayList<>();
return alterSqlList;
@ -64,10 +69,8 @@ public class SqlHelper {
* @param table
* @return
*/
public static String dropSql(Table table) {
StringBuilder sqlBuilder = new StringBuilder();
return sqlBuilder.toString();
public static String tableDropSql(Table table) {
return "DROP TABLE \"" + table.getName() + "\"";
}
/**

@ -6,8 +6,10 @@ import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.dynacmicform.config.spring.ContextHelper;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.Reader;
@ -15,19 +17,24 @@ import java.sql.Date;
import java.sql.*;
import java.util.*;
@Component
public class SqlExecutor {
private static final Logger log = LoggerFactory.getLogger(SqlExecutor.class);
private final SqlSession sqlSession;
public SqlExecutor(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
/**
* 检查SQL是否可以正常执行
*
* @param sql sql
* @return boolean
*/
public static boolean validateQuery(String sql) {
// 获取SqlSessionFactory实例
SqlSessionFactory sqlSessionFactory = getSessionFactory();
try (SqlSession session = sqlSessionFactory.openSession(); Connection conn = session.getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
public boolean validateQuery(String sql) {
try (Connection conn = getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
ResultSet rs = stmt.executeQuery();
rs.close();
log.debug("==> {}", sql);
@ -38,15 +45,15 @@ public class SqlExecutor {
}
}
public static boolean execute(String sql) throws Exception {
public boolean execute(String sql) throws Exception {
if (StringUtils.isEmpty(sql)) {
return false;
}
// 获取SqlSessionFactory实例
SqlSessionFactory sqlSessionFactory = getSessionFactory();
log.debug("==> SQL: " + sql);
try (SqlSession session = sqlSessionFactory.openSession(); Connection conn = session.getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
try {
Connection conn = sqlSession.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
return stmt.execute();
} catch (Exception e) {
log.error("执行sql查询异常: " + sql, e);
@ -61,15 +68,15 @@ public class SqlExecutor {
* @return
* @throws SQLException
*/
public static int[] executeBatch(Collection<String> sqlList) throws SQLException {
public int[] executeBatch(Collection<String> sqlList) throws SQLException {
int[] count = new int[sqlList.size()];
if (sqlList.isEmpty()) {
return count;
}
SqlSessionFactory sqlSessionFactory = getSessionFactory();
PreparedStatement stmt = null;
try (SqlSession session = sqlSessionFactory.openSession(); Connection conn = session.getConnection()) {
try {
Connection conn = getConnection();
conn.setAutoCommit(false);
for (String sql : sqlList) {
if (StringUtils.hasText(sql)) {
@ -102,12 +109,11 @@ public class SqlExecutor {
* @return boolean
* @throws Exception -
*/
public static boolean executeUpdate(String sql, Object... params) throws Exception {
public boolean executeUpdate(String sql, Object... params) throws Exception {
if (StringUtils.isEmpty(sql)) {
return false;
}
// 获取SqlSessionFactory实例
SqlSessionFactory sqlSessionFactory = getSessionFactory();
log.debug("==> SQL: " + sql);
// 替换单个?参数为多个,用于拼接IN参数
if (params != null && params.length > 0) {
@ -116,7 +122,9 @@ public class SqlExecutor {
log.warn("更新参数集合数量过多, size={},请检查调用是否合理!", params.length);
}
}
try (SqlSession session = sqlSessionFactory.openSession(); Connection conn = session.getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
try {
Connection conn = getConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
if (params != null && params.length > 0) {
for (int i = 0; i < params.length; i++) {
stmt.setObject(i + 1, params[i]);
@ -137,12 +145,11 @@ public class SqlExecutor {
* @param sql
* @return
*/
public static List<Map<String, Object>> executeQuery(String sql, Object... params) throws Exception {
public List<Map<String, Object>> executeQuery(String sql, Object... params) throws Exception {
if (StringUtils.isBlank(sql)) {
return null;
}
// 获取SqlSessionFactory实例
SqlSessionFactory sqlSessionFactory = getSessionFactory();
log.debug("==> SQL: " + sql);
// 替换单个?参数为多个,用于拼接IN参数
if (params != null && params.length > 0) {
@ -151,7 +158,9 @@ public class SqlExecutor {
log.warn("查询参数集合数量过多, size={},请检查调用是否合理!", params.length);
}
}
try (SqlSession session = sqlSessionFactory.openSession(); Connection conn = session.getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
try {
Connection conn = getConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
if (params != null && params.length > 0) {
for (int i = 0; i < params.length; i++) {
stmt.setObject(i + 1, params[i]);
@ -186,13 +195,8 @@ public class SqlExecutor {
}
}
private static SqlSessionFactory getSessionFactory() {
SqlSessionFactory sqlSessionFactory = ContextHelper.getBean(SqlSessionFactory.class);
if (sqlSessionFactory == null) {
log.warn("无法获取SqlSessionFactory实例,SQL将不被执行。");
throw new RuntimeException("获取SqlSessionFactory实例异常");
}
return sqlSessionFactory;
private Connection getConnection() throws SQLException {
return sqlSession.getConfiguration().getEnvironment().getDataSource().getConnection();
}
private static String clobRsConvert(Clob clob) {

@ -7,8 +7,11 @@ import com.keyware.shandan.system.entity.SysMenu;
import com.keyware.shandan.system.service.SysMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Component
@Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
public class DynamicFormListener implements DynamicFormEventListener {
@Autowired