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

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. 37
      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 结果 * @return 结果
*/ */
@PostMapping("/api/form/delete") @PostMapping("/api/form/delete")
public Result<Object> deleteFormInfo(int id) { public Result<Object> deleteFormInfo(int id) throws Exception {
return Result.of(dynamicFormService.delete(id)); return Result.of(dynamicFormService.delete(id));
} }
} }

@ -14,6 +14,12 @@ import java.util.*;
@Service @Service
public class DynamicDataService { public class DynamicDataService {
private final SqlExecutor sqlExecutor;
public DynamicDataService(SqlExecutor sqlExecutor) {
this.sqlExecutor = sqlExecutor;
}
/** /**
* 根据ID删除数据 * 根据ID删除数据
@ -25,7 +31,7 @@ public class DynamicDataService {
*/ */
public boolean deleteById(FormInfoPo form, Integer id) throws Exception { public boolean deleteById(FormInfoPo form, Integer id) throws Exception {
QueryParam param = QueryParam.builder().column("ID").eq(id).build(); 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,去除主键列 // 插入Sql,去除主键列
params.remove("ID"); params.remove("ID");
LinkedHashMap<String, Object> data = new LinkedHashMap<>(params); 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(); QueryParam queryParam = QueryParam.builder().column("ID").eq(id).build();
List<Object> paramValues = new ArrayList<>(dataMap.values()); List<Object> paramValues = new ArrayList<>(dataMap.values());
paramValues.addAll(queryParam.getParamValues()); 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 { public Map<String, Object> getById(FormInfoPo form, @NotNull Integer id) throws Exception {
QueryParam param = QueryParam.builder().column("ID").eq(id).build(); 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) { if (list == null) {
return null; return null;
} }
@ -105,12 +111,12 @@ public class DynamicDataService {
* @throws Exception - * @throws Exception -
*/ */
public Page<Map<String, Object>> pageList(FormInfoPo form, QueryParam params) 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; long count = 0;
if (countList != null && countList.size() > 0) { if (countList != null && countList.size() > 0) {
count = (long) countList.get(0).get("COUNT"); 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<Map<String, Object>> page = new Page<>(params.getPage(), params.getPageSize(), count);
page.setRecords(dataList); page.setRecords(dataList);
return page; return page;
@ -124,6 +130,6 @@ public class DynamicDataService {
* @throws Exception * @throws Exception
*/ */
public List<Map<String, Object>> list(FormInfoPo form) 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.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; 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.common.util.StringUtils;
import com.keyware.shandan.dynacmicform.core.DynamicFormEventListener; import com.keyware.shandan.dynacmicform.core.DynamicFormEventListener;
import com.keyware.shandan.dynacmicform.core.basic.entity.FormInfoPo; import com.keyware.shandan.dynacmicform.core.basic.entity.FormInfoPo;
@ -22,11 +23,14 @@ import java.util.List;
@Slf4j @Slf4j
@Service @Service
public class DynamicFormService { public class DynamicFormService {
private final SqlExecutor sqlExecutor;
private final FormInfoService formInfoService; private final FormInfoService formInfoService;
private final DynamicFormEventListener dynamicFormEventListener; 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.formInfoService = formInfoService;
this.dynamicFormEventListener = dynamicFormEventListener; this.dynamicFormEventListener = dynamicFormEventListener;
} }
@ -43,8 +47,8 @@ public class DynamicFormService {
FormInfoPo oldForm = formInfoService.getById(form.getId()); FormInfoPo oldForm = formInfoService.getById(form.getId());
Table table = TableInfoParser.parseTable(form); Table table = TableInfoParser.parseTable(form);
if (oldForm == null) { if (oldForm == null) {
String sql = SqlHelper.createSql(table); String sql = SqlHelper.tableCreateSql(table);
SqlExecutor.execute(sql); sqlExecutor.execute(sql);
} else { } else {
Table oldTable = TableInfoParser.parseTable(oldForm); Table oldTable = TableInfoParser.parseTable(oldForm);
List<String> alterSqlList = SqlHelper.alterTableDropColumnSql(oldTable, table); List<String> alterSqlList = SqlHelper.alterTableDropColumnSql(oldTable, table);
@ -53,7 +57,7 @@ public class DynamicFormService {
alterSqlList.addAll(SqlHelper.alterTableAddColumnSql(oldTable, table)); alterSqlList.addAll(SqlHelper.alterTableAddColumnSql(oldTable, table));
alterSqlList.addAll(SqlHelper.commentTableSql(oldTable, table)); alterSqlList.addAll(SqlHelper.commentTableSql(oldTable, table));
alterSqlList.addAll(SqlHelper.commentColumnSql(oldTable, table)); alterSqlList.addAll(SqlHelper.commentColumnSql(oldTable, table));
SqlExecutor.executeBatch(alterSqlList); sqlExecutor.executeBatch(alterSqlList);
} }
if (StringUtils.isBlank(form.getQueryConfig())) { if (StringUtils.isBlank(form.getQueryConfig())) {
generateQueryConfig(form); generateQueryConfig(form);
@ -67,19 +71,30 @@ public class DynamicFormService {
} }
/** /**
* 删除表单信息 * 删除表单信息逻辑删除并对实际数据表进行重命名备份
* *
* @param id * @param id
* @return * @return
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public boolean delete(Integer id) { public boolean delete(Integer id) throws Exception {
FormInfoPo form = formInfoService.getById(id); FormInfoPo form = formInfoService.getById(id);
boolean ok = formInfoService.removeById(id); if (form != null) {
if (ok) { // 对原始表结构进行重命名备份
dynamicFormEventListener.onDrop(form); 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) {
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.mapper.FormInfoMapper;
import com.keyware.shandan.dynacmicform.core.basic.services.FormInfoService; import com.keyware.shandan.dynacmicform.core.basic.services.FormInfoService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable; import java.io.Serializable;
@ -15,4 +17,10 @@ public class FormInfoServiceImpl extends ServiceImpl<FormInfoMapper, FormInfoPo>
public boolean removeById(Serializable id) { public boolean removeById(Serializable id) {
return super.removeById(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; package com.keyware.shandan.dynacmicform.core.db;
import cn.hutool.core.lang.Assert; 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.StreamUtil;
import com.keyware.shandan.common.util.StringUtils; import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.dynacmicform.core.basic.entity.FormInfoPo; import com.keyware.shandan.dynacmicform.core.basic.entity.FormInfoPo;
@ -23,7 +24,7 @@ public class SqlHelper {
* @param table * @param table
* @return * @return
*/ */
public static String createSql(Table table) { public static String tableCreateSql(Table table) {
StringBuilder sqlBuilder = new StringBuilder("CREATE TABLE "); StringBuilder sqlBuilder = new StringBuilder("CREATE TABLE ");
sqlBuilder.append("\"").append(table.getName()).append("\" ("); sqlBuilder.append("\"").append(table.getName()).append("\" (");
@ -46,13 +47,17 @@ public class SqlHelper {
return sqlBuilder.toString(); return sqlBuilder.toString();
} }
public static String tableRenameSql(String oldTableName, String newTableName) {
return StrUtil.format("alter table \"{}\" rename to \"{}\"", oldTableName, newTableName);
}
/** /**
* 修改表的sql * 修改表的sql
* *
* @param columns 修改的列集合 * @param columns 修改的列集合
* @return * @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<>(); List<String> alterSqlList = new ArrayList<>();
return alterSqlList; return alterSqlList;
@ -64,10 +69,8 @@ public class SqlHelper {
* @param table * @param table
* @return * @return
*/ */
public static String dropSql(Table table) { public static String tableDropSql(Table table) {
StringBuilder sqlBuilder = new StringBuilder(); return "DROP TABLE \"" + table.getName() + "\"";
return sqlBuilder.toString();
} }
/** /**

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