diff --git a/src/main/java/com/supervision/common/enums/ResultStatusEnum.java b/src/main/java/com/supervision/common/enums/ResultStatusEnum.java index 2fe0160..9b6790f 100644 --- a/src/main/java/com/supervision/common/enums/ResultStatusEnum.java +++ b/src/main/java/com/supervision/common/enums/ResultStatusEnum.java @@ -35,6 +35,7 @@ public enum ResultStatusEnum { USER_DOES_NOT_EXIST(507, "用户不存在,操作失败!"), ILLEGAL_ARGUMENT(508, "参数校验失败!"), + RUNTIME_EXCEPTION(509, "程序运行异常!"), IMPORT_COMPANY_FORMAT_ERROR(521,"Excel表格格式错误!"), IMPORT_COMPANY_FAIL(522,"部分数据导入失败"), INSERT_FAIL(600,"新增失败"), diff --git a/src/main/java/com/supervision/config/ExceptionHandlerConfig.java b/src/main/java/com/supervision/config/ExceptionHandlerConfig.java index e7b3107..b79a4fa 100644 --- a/src/main/java/com/supervision/config/ExceptionHandlerConfig.java +++ b/src/main/java/com/supervision/config/ExceptionHandlerConfig.java @@ -32,5 +32,11 @@ public class ExceptionHandlerConfig { return R.fail(ResultStatusEnum.ILLEGAL_ARGUMENT,exception.getMessage()); } - + @ExceptionHandler(RuntimeException.class) + public R manualValidationExceptionResponse(RuntimeException exception) { + log.error("=========运行异常=========>>>"); + log.error(exception.getMessage(), exception); + log.error("<<<=========运行异常========="); + return R.fail(ResultStatusEnum.RUNTIME_EXCEPTION,exception.getMessage()); + } } diff --git a/src/main/java/com/supervision/police/dto/AnalyseCaseDTO.java b/src/main/java/com/supervision/police/dto/AnalyseCaseDTO.java index 64453f3..cbbb836 100644 --- a/src/main/java/com/supervision/police/dto/AnalyseCaseDTO.java +++ b/src/main/java/com/supervision/police/dto/AnalyseCaseDTO.java @@ -1,6 +1,7 @@ package com.supervision.police.dto; import com.supervision.police.domain.ModelAtomicIndex; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.util.List; @@ -23,6 +24,10 @@ public class AnalyseCaseDTO { */ private String lawParty; + + @Schema(description = "证据名称") + private String evidenceName; + /** * 原子指标列表 */ diff --git a/src/main/java/com/supervision/police/mybatis/RowMapperStatementBuilder.java b/src/main/java/com/supervision/police/mybatis/RowMapperStatementBuilder.java new file mode 100644 index 0000000..a2bae54 --- /dev/null +++ b/src/main/java/com/supervision/police/mybatis/RowMapperStatementBuilder.java @@ -0,0 +1,197 @@ +package com.supervision.police.mybatis; + +import cn.hutool.crypto.digest.MD5; +import org.apache.ibatis.builder.StaticSqlSource; +import org.apache.ibatis.mapping.*; +import org.apache.ibatis.scripting.LanguageDriver; +import org.apache.ibatis.session.Configuration; + +import java.util.ArrayList; +import java.util.Map; + +/** + * 一个基于mybatis简单粗暴的构建MappedStatement的实现 + */ +public class RowMapperStatementBuilder { + private final Configuration configuration; + private final LanguageDriver languageDriver; + + public RowMapperStatementBuilder(Configuration configuration) { + this.configuration = configuration; + this.languageDriver = configuration.getDefaultScriptingLanguageInstance(); + } + + /** + * 创建MSID + * + * @param sql 执行的sql + * @param sql 执行的sqlCommandType + * @return + */ + private String generateMappedStatementId(String sql, SqlCommandType sqlCommandType) { + return sqlCommandType.toString() + "." + MD5.create().digestHex(sql); + } + + /** + * 是否已经存在该ID + * + * @param msId + * @return + */ + private boolean hasMappedStatement(String msId) { + return configuration.hasStatement(msId, false); + } + + /** + * 创建一个查询的MS + * + * @param msId + * @param sqlSource 执行的sqlSource + * @param resultType 返回的结果类型 + */ + private void cacheSelectMappedStatement(String msId, SqlSource sqlSource, final Class resultType) { + + if (configuration.hasStatement(msId,false)){ + return; + } + MappedStatement ms = new MappedStatement.Builder(configuration, msId, sqlSource, SqlCommandType.SELECT) + .resultMaps(new ArrayList() { + { + add(new ResultMap.Builder(configuration, "defaultResultMap", resultType, new ArrayList(0)).build()); + } + }) + .build(); + //缓存MappedStatement + configuration.addMappedStatement(ms); + } + + /** + * 创建一个简单的MS + * + * @param msId + * @param sqlSource 执行的sqlSource + * @param sqlCommandType 执行的sqlCommandType + */ + private void newUpdateMappedStatement(String msId, SqlSource sqlSource, SqlCommandType sqlCommandType) { + MappedStatement ms = new MappedStatement.Builder(configuration, msId, sqlSource, sqlCommandType) + .resultMaps(new ArrayList() { + { + add(new ResultMap.Builder(configuration, "defaultResultMap", int.class, new ArrayList(0)).build()); + } + }) + .build(); + //缓存 + configuration.addMappedStatement(ms); + } + + public String select(String sql) { + String msId = generateMappedStatementId(sql, SqlCommandType.SELECT); + if (hasMappedStatement(msId)) { + return msId; + } + StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql); + cacheSelectMappedStatement(msId, sqlSource, Map.class); + return msId; + } + + + public MappedStatement selectMappedStatement(String sql, Class resultType) { + String msId = generateMappedStatementId(sql, SqlCommandType.SELECT); + if (hasMappedStatement(msId)) { + return configuration.getMappedStatement(msId, false); + } + StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql); + cacheSelectMappedStatement(msId, sqlSource, resultType); + return configuration.getMappedStatement(msId, false); + } + + public String selectDynamic(String sql, Class parameterType) { + String msId = generateMappedStatementId(sql , SqlCommandType.SELECT); + if (hasMappedStatement(msId)) { + return msId; + } + SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, parameterType); + cacheSelectMappedStatement(msId, sqlSource, Map.class); + return msId; + } + + public String select(String sql, Class resultType) { + String msId = generateMappedStatementId(resultType + sql, SqlCommandType.SELECT); + if (hasMappedStatement(msId)) { + return msId; + } + StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql); + cacheSelectMappedStatement(msId, sqlSource, resultType); + return msId; + } + + public String selectDynamic(String sql, Class parameterType, Class resultType) { + String msId = generateMappedStatementId(resultType + sql + parameterType, SqlCommandType.SELECT); + if (hasMappedStatement(msId)) { + return msId; + } + SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, parameterType); + cacheSelectMappedStatement(msId, sqlSource, resultType); + return msId; + } + + public String insert(String sql) { + String msId = generateMappedStatementId(sql, SqlCommandType.INSERT); + if (hasMappedStatement(msId)) { + return msId; + } + StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql); + newUpdateMappedStatement(msId, sqlSource, SqlCommandType.INSERT); + return msId; + } + + public String insertDynamic(String sql, Class parameterType) { + String msId = generateMappedStatementId(sql + parameterType, SqlCommandType.INSERT); + if (hasMappedStatement(msId)) { + return msId; + } + SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, parameterType); + newUpdateMappedStatement(msId, sqlSource, SqlCommandType.INSERT); + return msId; + } + + public String update(String sql) { + String msId = generateMappedStatementId(sql, SqlCommandType.UPDATE); + if (hasMappedStatement(msId)) { + return msId; + } + StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql); + newUpdateMappedStatement(msId, sqlSource, SqlCommandType.UPDATE); + return msId; + } + + public String updateDynamic(String sql, Class parameterType) { + String msId = generateMappedStatementId(sql + parameterType, SqlCommandType.UPDATE); + if (hasMappedStatement(msId)) { + return msId; + } + SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, parameterType); + newUpdateMappedStatement(msId, sqlSource, SqlCommandType.UPDATE); + return msId; + } + + public String delete(String sql) { + String msId = generateMappedStatementId(sql, SqlCommandType.DELETE); + if (hasMappedStatement(msId)) { + return msId; + } + StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql); + newUpdateMappedStatement(msId, sqlSource, SqlCommandType.DELETE); + return msId; + } + + public String deleteDynamic(String sql, Class parameterType) { + String msId = generateMappedStatementId(sql + parameterType, SqlCommandType.DELETE); + if (hasMappedStatement(msId)) { + return msId; + } + SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, parameterType); + newUpdateMappedStatement(msId, sqlSource, SqlCommandType.DELETE); + return msId; + } +} diff --git a/src/main/java/com/supervision/police/mybatis/RowSqlMapper.java b/src/main/java/com/supervision/police/mybatis/RowSqlMapper.java new file mode 100644 index 0000000..66bff8c --- /dev/null +++ b/src/main/java/com/supervision/police/mybatis/RowSqlMapper.java @@ -0,0 +1,239 @@ +package com.supervision.police.mybatis; + +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.exceptions.TooManyResultsException; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.session.SqlSession; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +/** + * 基于mybatis直接执行sql语句的工具类 + */ +@Slf4j +@Component +public class RowSqlMapper { + + private final RowMapperStatementBuilder mapperStatementBuilder; + private final SqlSession sqlSession; + + /** + * 构造方法,默认缓存MappedStatement + * + * @param sqlSession + */ + public RowSqlMapper(SqlSession sqlSession) { + this.sqlSession = sqlSession; + this.mapperStatementBuilder = new RowMapperStatementBuilder(sqlSession.getConfiguration()); + } + + /** + * 获取List中最多只有一个的数据 + * + * @param list List结果 + * @param 泛型类型 + * @return + */ + private T getOne(List list) { + if (list.size() == 1) { + return list.get(0); + } else if (list.size() > 1) { + throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size()); + } else { + return null; + } + } + + /** + * 查询返回一个结果,多个结果时抛出异常 + * + * @param sql 执行的sql + * @return + */ + public Map selectOne(String sql) { + List> list = selectList(sql); + return getOne(list); + } + + /** + * 查询返回一个结果,多个结果时抛出异常 + * + * @param sql 执行的sql + * @param value 参数 + * @return + */ + public Map selectOne(String sql, Object value) { + List> list = selectList(sql, value); + return getOne(list); + } + + /** + * 查询返回一个结果,多个结果时抛出异常 + * + * @param sql 执行的sql + * @param resultType 返回的结果类型 + * @param 泛型类型 + * @return + */ + public T selectOne(String sql, Class resultType) { + List list = selectList(sql, resultType); + return getOne(list); + } + + /** + * 查询返回一个结果,多个结果时抛出异常 + * + * @param sql 执行的sql + * @param value 参数 + * @param resultType 返回的结果类型 + * @param 泛型类型 + * @return + */ + public T selectOne(String sql, Object value, Class resultType) { + List list = selectList(sql, value, resultType); + return getOne(list); + } + + /** + * 查询返回List> + * + * @param sql 执行的sql + * @return + */ + public List> selectList(String sql) { + String msId = mapperStatementBuilder.select(sql); + return sqlSession.selectList(msId); + } + + /** + * 查询返回List> + * + * @param sql 执行的sql + * @param value 参数 + * @return + */ + public List> selectList(String sql, Object value) { + log.info("selectList sql:{},params:{}", sql, JSONUtil.toJsonStr(value)); + Class parameterType = value != null ? value.getClass() : null; + String msId = mapperStatementBuilder.selectDynamic(sql, parameterType); + return sqlSession.selectList(msId, value); + } + + /** + * 查询返回指定的结果类型 + * + * @param sql 执行的sql + * @param resultType 返回的结果类型 + * @param 泛型类型 + * @return + */ + public List selectList(String sql, Class resultType) { + String msId; + if (resultType == null) { + msId = mapperStatementBuilder.select(sql); + } else { + msId = mapperStatementBuilder.select(sql, resultType); + } + return sqlSession.selectList(msId); + } + + /** + * 查询返回指定的结果类型 + * + * @param sql 执行的sql + * @param value 参数 + * @param resultType 返回的结果类型 + * @param 泛型类型 + * @return + */ + public List selectList(String sql, Object value, Class resultType) { + String msId; + Class parameterType = value != null ? value.getClass() : null; + if (resultType == null) { + msId = mapperStatementBuilder.selectDynamic(sql, parameterType); + } else { + msId = mapperStatementBuilder.selectDynamic(sql, parameterType, resultType); + } + return sqlSession.selectList(msId, value); + } + + /** + * 插入数据 + * + * @param sql 执行的sql + * @return + */ + public int insert(String sql) { + String msId = mapperStatementBuilder.insert(sql); + return sqlSession.insert(msId); + } + + /** + * 插入数据 + * + * @param sql 执行的sql + * @param value 参数 + * @return + */ + public int insert(String sql, Object value) { + Class parameterType = value != null ? value.getClass() : null; + String msId = mapperStatementBuilder.insertDynamic(sql, parameterType); + return sqlSession.insert(msId, value); + } + + /** + * 更新数据 + * + * @param sql 执行的sql + * @return + */ + public int update(String sql) { + String msId = mapperStatementBuilder.update(sql); + return sqlSession.update(msId); + } + + /** + * 更新数据 + * + * @param sql 执行的sql + * @param value 参数 + * @return + */ + public int update(String sql, Object value) { + Class parameterType = value != null ? value.getClass() : null; + String msId = mapperStatementBuilder.updateDynamic(sql, parameterType); + return sqlSession.update(msId, value); + } + + /** + * 删除数据 + * + * @param sql 执行的sql + * @return + */ + public int delete(String sql) { + String msId = mapperStatementBuilder.delete(sql); + return sqlSession.delete(msId); + } + + /** + * 删除数据 + * + * @param sql 执行的sql + * @param value 参数 + * @return + */ + public int delete(String sql, Object value) { + Class parameterType = value != null ? value.getClass() : null; + String msId = mapperStatementBuilder.deleteDynamic(sql, parameterType); + return sqlSession.delete(msId, value); + } + + public MappedStatement selectMappedStatement(String sql, Class resultType) { + return mapperStatementBuilder.selectMappedStatement(sql, resultType); + } + +} diff --git a/src/main/java/com/supervision/police/service/impl/ModelServiceImpl.java b/src/main/java/com/supervision/police/service/impl/ModelServiceImpl.java index c409a17..e0cc70e 100644 --- a/src/main/java/com/supervision/police/service/impl/ModelServiceImpl.java +++ b/src/main/java/com/supervision/police/service/impl/ModelServiceImpl.java @@ -2,6 +2,7 @@ package com.supervision.police.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -15,6 +16,7 @@ import com.supervision.police.dto.AtomicData; import com.supervision.police.dto.JudgeLogic; import com.supervision.police.dto.caseScore.CaseScoreDetailBuilder; import com.supervision.police.mapper.*; +import com.supervision.police.mybatis.RowSqlMapper; import com.supervision.police.service.ModelService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -44,6 +46,8 @@ public class ModelServiceImpl implements ModelService { private final CasePersonMapper casePersonMapper; + private final RowSqlMapper rowSqlMapper; + @Override public R analyseCase(AnalyseCaseDTO analyseCaseDTO) { ModelCase modelCase = modelCaseMapper.selectById(analyseCaseDTO.getCaseId()); @@ -76,6 +80,7 @@ public class ModelServiceImpl implements ModelService { // list } else if ("2".endsWith(atomicIndex.getIndexSource()) && StringUtils.isNotEmpty(ql)) { // + analyseDataBaseCase(analyseCaseDTO, result, ql); } else if ("3".endsWith(atomicIndex.getIndexSource()) && StringUtils.isNotEmpty(ql)) { // 使用知识图谱进行计算 analyseGraphCase(analyseCaseDTO, result, ql); @@ -272,4 +277,59 @@ public class ModelServiceImpl implements ModelService { } } + + /** + * 分析数据库类型的原子信息 + * @param analyseCaseDTO + * @param result + * @param sql + */ + private void analyseDataBaseCase(AnalyseCaseDTO analyseCaseDTO, ModelAtomicResult result, String sql) { + + Map params = new HashMap<>(); + params.put("caseId", result.getCaseId()); + params.put("evidenceName", analyseCaseDTO.getEvidenceName()); + params.put("provider", null); + params.put("party_a", analyseCaseDTO.getLawActorName()); + params.put("party_b", analyseCaseDTO.getLawParty()); + + /* + todo:添加语法解析功能,提前验证sql是否合法,并且限制sql智能是select语句和限制sql语句中出现的表 + MappedStatement mappedStatement = rowSqlMapper.selectMappedStatement(sql, Map.class); + BoundSql boundSql = mappedStatement.getBoundSql(params); + String sql1 = boundSql.getSql(); + */ + + boolean b = parseResult(rowSqlMapper.selectList(sql, params, Map.class)); + result.setAtomicResult(b ? "1" : "0"); + + + } + + /** + * 执行结果分析: + * 1. 如果查询出的结果只有一行,判断列数是否大于1,如果大于1,返回真,如果=1,继续判断值是否大于0,如果大于0,返回真,如果=0,返回假 + *2. 如果查询出的结果大于一行,则返回真 + * @param mapList 查询结果 + * @return + */ + private boolean parseResult(List mapList) { + + if (CollUtil.isEmpty(mapList)) { + return false; + } + + if (CollUtil.size(mapList) > 1){ + return true; + } + + Map firstRow = CollUtil.getFirst(mapList); + if (firstRow.size() == 1 && CollUtil.size(firstRow.values())==1) { + Object first = CollUtil.getFirst(firstRow.values()); + if (NumberUtil.isNumber(first.toString())) { + return NumberUtil.parseInt(first.toString()) > 0; + } + } + return true; + } }