Merge remote-tracking branch 'origin/master'
# Conflicts: # ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/domain/WmsInventory.javahwmom-htk
commit
cf2ed1ceaa
@ -0,0 +1,15 @@
|
||||
package org.dromara.common.constant;
|
||||
|
||||
/**
|
||||
* MES常量信息
|
||||
*
|
||||
* @author xins
|
||||
*/
|
||||
public interface HwMomAiConstants {
|
||||
|
||||
/**
|
||||
* redis存储数据库表结构key
|
||||
*/
|
||||
public static final String AI_DATABASE_SCHEMA_KEY_PREFIX = "ai:database:schema:";
|
||||
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package org.dromara.ai.domain.bo;
|
||||
|
||||
import org.dromara.ai.domain.AiSqlTable;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import jakarta.validation.constraints.*;
|
||||
|
||||
/**
|
||||
* AI生成sql信息业务对象 ai_sql_table
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-09-04
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = AiSqlTable.class, reverseConvertGenerate = false)
|
||||
public class AiSqlTableBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@NotNull(message = "编号不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Long tableId;
|
||||
|
||||
/**
|
||||
* 数据源
|
||||
*/
|
||||
private String dataName;
|
||||
|
||||
/**
|
||||
* 表名称
|
||||
*/
|
||||
@NotBlank(message = "表名称不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String tableName;
|
||||
|
||||
/**
|
||||
* 表描述
|
||||
*/
|
||||
@NotBlank(message = "表描述不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String tableComment;
|
||||
|
||||
/**
|
||||
* 关联子表的表名
|
||||
*/
|
||||
@NotBlank(message = "关联子表的表名不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String subTableName;
|
||||
|
||||
/**
|
||||
* 子表关联的外键名
|
||||
*/
|
||||
@NotBlank(message = "子表关联的外键名不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String subTableFkName;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package org.dromara.ai.domain.dto;
|
||||
|
||||
/**
|
||||
* @description AiSqlTable Delete dto
|
||||
* @author xins
|
||||
* @date 2025/9/5 14:50
|
||||
*/
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
|
||||
@Data
|
||||
public class AiSqlTableDelete {
|
||||
/**
|
||||
* 表ID
|
||||
*/
|
||||
@NotNull(message = "表ID不能为空", groups = { EditGroup.class })
|
||||
private Long tableId;
|
||||
|
||||
/**
|
||||
* 表名称
|
||||
*/
|
||||
@NotBlank(message = "表名不能为空", groups = { EditGroup.class })
|
||||
private String tableName;
|
||||
|
||||
/**
|
||||
* 数据源名称
|
||||
*/
|
||||
@NotBlank(message = "数据源名称不能为空", groups = { EditGroup.class })
|
||||
private String dataName;
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,67 @@
|
||||
package org.dromara.ai.domain.vo;
|
||||
|
||||
import org.dromara.ai.domain.AiSqlTable;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import org.dromara.common.excel.annotation.ExcelDictFormat;
|
||||
import org.dromara.common.excel.convert.ExcelDictConvert;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* AI生成sql信息视图对象 ai_sql_table
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-09-04
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = AiSqlTable.class)
|
||||
public class AiSqlTableVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@ExcelProperty(value = "编号")
|
||||
private Long tableId;
|
||||
|
||||
/**
|
||||
* 数据源
|
||||
*/
|
||||
private String dataName;
|
||||
|
||||
/**
|
||||
* 表名称
|
||||
*/
|
||||
@ExcelProperty(value = "表名称")
|
||||
private String tableName;
|
||||
|
||||
/**
|
||||
* 表描述
|
||||
*/
|
||||
@ExcelProperty(value = "表描述")
|
||||
private String tableComment;
|
||||
|
||||
/**
|
||||
* 关联子表的表名
|
||||
*/
|
||||
@ExcelProperty(value = "关联子表的表名")
|
||||
private String subTableName;
|
||||
|
||||
/**
|
||||
* 子表关联的外键名
|
||||
*/
|
||||
@ExcelProperty(value = "子表关联的外键名")
|
||||
private String subTableFkName;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,101 @@
|
||||
package org.dromara.ai.service;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
|
||||
import org.dromara.ai.domain.AiSqlTable;
|
||||
import org.dromara.ai.domain.dto.AiSqlTableDelete;
|
||||
import org.dromara.ai.domain.vo.AiSqlTableVo;
|
||||
import org.dromara.ai.domain.bo.AiSqlTableBo;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* AI生成sql信息Service接口
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-09-04
|
||||
*/
|
||||
public interface IAiSqlTableService {
|
||||
|
||||
/**
|
||||
* 查询AI生成sql信息
|
||||
*
|
||||
* @param tableId 主键
|
||||
* @return AI生成sql信息
|
||||
*/
|
||||
AiSqlTableVo queryById(Long tableId);
|
||||
|
||||
/**
|
||||
* 分页查询AI生成sql信息列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return AI生成sql信息分页列表
|
||||
*/
|
||||
TableDataInfo<AiSqlTableVo> queryPageList(AiSqlTableBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询符合条件的AI生成sql信息列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return AI生成sql信息列表
|
||||
*/
|
||||
List<AiSqlTableVo> queryList(AiSqlTableBo bo);
|
||||
|
||||
/**
|
||||
* 新增AI生成sql信息
|
||||
*
|
||||
* @param bo AI生成sql信息
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
Boolean insertByBo(AiSqlTableBo bo);
|
||||
|
||||
/**
|
||||
* 修改AI生成sql信息
|
||||
*
|
||||
* @param bo AI生成sql信息
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateByBo(AiSqlTableBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除AI生成sql信息信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 查询数据库列表
|
||||
*
|
||||
* @param aiSqlTableBo AiSqlTableBo
|
||||
* @param pageQuery 包含分页信息的PageQuery对象
|
||||
* @return 包含分页结果的TableDataInfo对象
|
||||
*/
|
||||
public TableDataInfo<AiSqlTable> selectPageDbTableList(AiSqlTableBo aiSqlTableBo, PageQuery pageQuery);
|
||||
|
||||
|
||||
/**
|
||||
* 导入表结构
|
||||
*
|
||||
* @param aiSqlTableList 导入表列表
|
||||
*/
|
||||
public boolean importAiSqlTable(List<AiSqlTable> aiSqlTableList);
|
||||
|
||||
/**
|
||||
* 刷新缓存
|
||||
*/
|
||||
public void refreshCache();
|
||||
|
||||
/**
|
||||
* 删除AI生成sql信息
|
||||
* @param aiSqlTableDeleteList
|
||||
*/
|
||||
public void deleteAiSqlTable(List<AiSqlTableDelete> aiSqlTableDeleteList);
|
||||
|
||||
}
|
||||
@ -0,0 +1,333 @@
|
||||
package org.dromara.ai.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import org.dromara.ai.domain.dto.AiSqlTableDelete;
|
||||
import org.dromara.ai.mapper.SQLServerDatabaseMetaMapper;
|
||||
import org.dromara.ai.utils.DbSchemaUtils;
|
||||
import org.dromara.common.constant.HwMomAiConstants;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.github.yulichang.toolkit.JoinWrappers;
|
||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.ai.domain.bo.AiSqlTableBo;
|
||||
import org.dromara.ai.domain.vo.AiSqlTableVo;
|
||||
import org.dromara.ai.domain.AiSqlTable;
|
||||
import org.dromara.ai.mapper.AiSqlTableMapper;
|
||||
import org.dromara.ai.service.IAiSqlTableService;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.anyline.metadata.Column;
|
||||
import org.anyline.metadata.Table;
|
||||
import org.anyline.proxy.ServiceProxy;
|
||||
import org.dromara.common.core.constant.Constants;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.core.utils.file.FileUtils;
|
||||
import org.dromara.common.json.utils.JsonUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* AI生成sql信息Service业务层处理
|
||||
*
|
||||
* @author xins
|
||||
* @date 2025-09-04
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class AiSqlTableServiceImpl implements IAiSqlTableService {
|
||||
private static final String[] TABLE_IGNORE = new String[]{"sj_", "act_", "flw_", "gen_"};
|
||||
|
||||
private final AiSqlTableMapper baseMapper;
|
||||
|
||||
private final SQLServerDatabaseMetaMapper sqlServerDatabaseMetaMapper;
|
||||
|
||||
private final StringRedisTemplate redisTemplate;
|
||||
|
||||
/**
|
||||
* 查询AI生成sql信息
|
||||
*
|
||||
* @param tableId 主键
|
||||
* @return AI生成sql信息
|
||||
*/
|
||||
@Override
|
||||
public AiSqlTableVo queryById(Long tableId) {
|
||||
return baseMapper.selectVoById(tableId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询AI生成sql信息列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return AI生成sql信息分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<AiSqlTableVo> queryPageList(AiSqlTableBo bo, PageQuery pageQuery) {
|
||||
MPJLambdaWrapper<AiSqlTable> lqw = buildQueryWrapper(bo);
|
||||
Page<AiSqlTableVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询符合条件的AI生成sql信息列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return AI生成sql信息列表
|
||||
*/
|
||||
@Override
|
||||
public List<AiSqlTableVo> queryList(AiSqlTableBo bo) {
|
||||
MPJLambdaWrapper<AiSqlTable> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private MPJLambdaWrapper<AiSqlTable> buildQueryWrapper(AiSqlTableBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
MPJLambdaWrapper<AiSqlTable> lqw = JoinWrappers.lambda(AiSqlTable.class)
|
||||
.selectAll(AiSqlTable.class)
|
||||
.eq(bo.getTableId() != null, AiSqlTable::getTableId, bo.getTableId())
|
||||
.like(StringUtils.isNotBlank(bo.getTableName()), AiSqlTable::getTableName, bo.getTableName())
|
||||
.like(StringUtils.isNotBlank(bo.getTableComment()), AiSqlTable::getTableComment, bo.getTableComment())
|
||||
.like(StringUtils.isNotBlank(bo.getSubTableName()), AiSqlTable::getSubTableName, bo.getSubTableName())
|
||||
.like(StringUtils.isNotBlank(bo.getSubTableFkName()), AiSqlTable::getSubTableFkName, bo.getSubTableFkName())
|
||||
.orderByDesc(AiSqlTable::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增AI生成sql信息
|
||||
*
|
||||
* @param bo AI生成sql信息
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(AiSqlTableBo bo) {
|
||||
AiSqlTable add = MapstructUtils.convert(bo, AiSqlTable.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setTableId(add.getTableId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改AI生成sql信息
|
||||
*
|
||||
* @param bo AI生成sql信息
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(AiSqlTableBo bo) {
|
||||
AiSqlTable update = MapstructUtils.convert(bo, AiSqlTable.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(AiSqlTable entity) {
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除AI生成sql信息信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询数据库列表
|
||||
*
|
||||
* @param aiSqlTableBo AiSqlTableBo
|
||||
* @param pageQuery 包含分页信息的PageQuery对象
|
||||
* @return 包含分页结果的TableDataInfo对象
|
||||
*/
|
||||
@DS("#aiSqlTableBo.dataName")
|
||||
@Override
|
||||
public TableDataInfo<AiSqlTable> selectPageDbTableList(AiSqlTableBo aiSqlTableBo, PageQuery pageQuery) {
|
||||
// 获取查询条件
|
||||
String tableName = aiSqlTableBo.getTableName();
|
||||
String tableComment = aiSqlTableBo.getTableComment();
|
||||
|
||||
LinkedHashMap<String, Table<?>> tablesMap = ServiceProxy.metadata().tables();
|
||||
if (CollUtil.isEmpty(tablesMap)) {
|
||||
return TableDataInfo.build();
|
||||
}
|
||||
List<String> tableNames = baseMapper.selectTableNameList(aiSqlTableBo.getDataName());
|
||||
String[] tableArrays;
|
||||
if (CollUtil.isNotEmpty(tableNames)) {
|
||||
tableArrays = tableNames.toArray(new String[0]);
|
||||
} else {
|
||||
tableArrays = new String[0];
|
||||
}
|
||||
// 过滤并转换表格数据
|
||||
List<AiSqlTable> tables = tablesMap.values().stream()
|
||||
.filter(x -> !startWithAnyIgnoreCase(x.getName(), TABLE_IGNORE))
|
||||
.filter(x -> {
|
||||
if (CollUtil.isEmpty(tableNames)) {
|
||||
return true;
|
||||
}
|
||||
return !StringUtils.equalsAnyIgnoreCase(x.getName(), tableArrays);
|
||||
})
|
||||
.filter(x -> {
|
||||
boolean nameMatches = true;
|
||||
boolean commentMatches = true;
|
||||
// 进行表名称的模糊查询
|
||||
if (StringUtils.isNotBlank(tableName)) {
|
||||
nameMatches = StringUtils.containsIgnoreCase(x.getName(), tableName);
|
||||
}
|
||||
// 进行表描述的模糊查询
|
||||
if (StringUtils.isNotBlank(tableComment)) {
|
||||
commentMatches = StringUtils.containsIgnoreCase(x.getComment(), tableComment);
|
||||
}
|
||||
// 同时匹配名称和描述
|
||||
return nameMatches && commentMatches;
|
||||
})
|
||||
.map(x -> {
|
||||
AiSqlTable gen = new AiSqlTable();
|
||||
gen.setTableName(x.getName());
|
||||
gen.setTableComment(x.getComment());
|
||||
gen.setCreateTime(x.getCreateTime());
|
||||
gen.setUpdateTime(x.getUpdateTime());
|
||||
return gen;
|
||||
}).toList();
|
||||
|
||||
IPage<AiSqlTable> page = pageQuery.build();
|
||||
page.setTotal(tables.size());
|
||||
// 手动分页 set数据
|
||||
page.setRecords(CollUtil.page((int) page.getCurrent() - 1, (int) page.getSize(), tables));
|
||||
return TableDataInfo.build(page);
|
||||
}
|
||||
|
||||
|
||||
public static boolean startWithAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) {
|
||||
// 判断是否是以指定字符串开头
|
||||
for (CharSequence searchCharSequence : searchCharSequences) {
|
||||
if (StringUtils.startsWithIgnoreCase(cs, searchCharSequence)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入表结构
|
||||
*
|
||||
* @param aiSqlTableList 导入表列表
|
||||
*/
|
||||
@DSTransactional
|
||||
@Override
|
||||
public boolean importAiSqlTable(List<AiSqlTable> aiSqlTableList) {
|
||||
AiSqlTable aiSqlTable = aiSqlTableList.get(0);
|
||||
String dbSchema = redisTemplate.opsForValue().get(HwMomAiConstants.AI_DATABASE_SCHEMA_KEY_PREFIX + aiSqlTable.getDataName());
|
||||
JSONObject dbSchemaJson;
|
||||
if (dbSchema == null) {
|
||||
dbSchemaJson = new JSONObject();
|
||||
} else {
|
||||
dbSchemaJson = JSON.parseObject(dbSchema);
|
||||
}
|
||||
|
||||
getTableSchema(dbSchemaJson, aiSqlTableList);
|
||||
|
||||
return baseMapper.insertBatch(aiSqlTableList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 刷新缓存
|
||||
*/
|
||||
@Override
|
||||
public void refreshCache() {
|
||||
JSONObject dbSchemaJson = new JSONObject();
|
||||
List<AiSqlTable> aiSqlTableList = baseMapper.selectList();
|
||||
getTableSchema(dbSchemaJson, aiSqlTableList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除AI生成sql信息
|
||||
* @param aiSqlTableDeleteList
|
||||
*/
|
||||
@Override
|
||||
public void deleteAiSqlTable(List<AiSqlTableDelete> aiSqlTableDeleteList) {
|
||||
List<Long> tableIds = aiSqlTableDeleteList.stream().map(AiSqlTableDelete::getTableId).collect(Collectors.toList());
|
||||
baseMapper.deleteByIds(tableIds);
|
||||
String dataName = aiSqlTableDeleteList.get(0).getDataName();
|
||||
String dbSchema = redisTemplate.opsForValue().get(HwMomAiConstants.AI_DATABASE_SCHEMA_KEY_PREFIX + dataName);
|
||||
if (StringUtils.isNotBlank(dbSchema)) {
|
||||
JSONObject dbSchemaJson = JSON.parseObject(dbSchema);
|
||||
for (AiSqlTableDelete aiSqlTableDelete : aiSqlTableDeleteList) {
|
||||
String tableName = aiSqlTableDelete.getTableName();
|
||||
dbSchemaJson.remove(tableName);
|
||||
}
|
||||
|
||||
redisTemplate.opsForValue().set(HwMomAiConstants.AI_DATABASE_SCHEMA_KEY_PREFIX + dataName,dbSchemaJson.toJSONString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void getTableSchema(JSONObject dbSchemaJson, List<AiSqlTable> aiSqlTableList) {
|
||||
String dataName = aiSqlTableList.get(0).getDataName();
|
||||
for (AiSqlTable aiSqlTable : aiSqlTableList) {
|
||||
String tableName = aiSqlTable.getTableName();
|
||||
List<Map<String, Object>> tableStructures = sqlServerDatabaseMetaMapper.getTableStructure(tableName);
|
||||
List<String> primaryKeys = sqlServerDatabaseMetaMapper.getPrimaryKeys(tableName);
|
||||
String schema = DbSchemaUtils.getFormatSchema(tableName, aiSqlTable.getTableComment(), tableStructures, primaryKeys);
|
||||
dbSchemaJson.put(tableName, schema);
|
||||
}
|
||||
|
||||
redisTemplate.opsForValue().set(HwMomAiConstants.AI_DATABASE_SCHEMA_KEY_PREFIX + dataName, dbSchemaJson.toJSONString());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package org.dromara.ai.utils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author xins
|
||||
* @Date 2025/9/5 13:30
|
||||
* @Description: 数据库表结构格式处理
|
||||
*/
|
||||
public class DbSchemaUtils {
|
||||
|
||||
public static String getFormatSchema(String tableName, String tableComment,List<Map<String, Object>> columns, List<String> primaryKeys) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("- 表名: ").append(tableName).append("\n");
|
||||
sb.append(" 主键: ").append(String.join(", ", primaryKeys)).append("\n");
|
||||
sb.append(" 表描述: ").append(tableComment).append("\n");
|
||||
sb.append(" 字段:\n");
|
||||
|
||||
for (Map<String, Object> column : columns) {
|
||||
sb.append(" * ")
|
||||
.append(column.get("columnName"))
|
||||
.append(" (").append(column.get("dataType"));
|
||||
|
||||
if (column.get("maxLength") != null && (short) column.get("maxLength") > 0) {
|
||||
sb.append(", 长度: ").append(column.get("maxLength"));
|
||||
}
|
||||
if (column.get("precision") != null && (short) column.get("precision") > 0) {
|
||||
sb.append(", 精度: ").append(column.get("precision"));
|
||||
}
|
||||
if (column.get("scale") != null && (short) column.get("scale") > 0) {
|
||||
sb.append(", 小数位: ").append(column.get("scale"));
|
||||
}
|
||||
|
||||
sb.append(column.get("nullable").equals(1) ? ", 可空" : ", 非空");
|
||||
|
||||
if (!((String) column.get("defaultValue")).isEmpty()) {
|
||||
sb.append(", 默认值: ").append(column.get("defaultValue"));
|
||||
}
|
||||
|
||||
if (!((String) column.get("description")).isEmpty()) {
|
||||
sb.append(", 描述: ").append(column.get("description"));
|
||||
}
|
||||
|
||||
sb.append(")\n");
|
||||
}
|
||||
sb.append("\n");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -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="org.dromara.ai.mapper.AiSqlTableMapper">
|
||||
|
||||
<select id="selectTableNameList" resultType="java.lang.String">
|
||||
select table_name from ai_sql_table where data_name = #{dataName,jdbcType=VARCHAR}
|
||||
</select>
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue