package com.vci.ubcs.ddl.service.impl; import com.alibaba.nacos.client.naming.NacosNamingService; import com.vci.starter.word.bo.WordMergeStartTableDataBO; import com.vci.ubcs.ddl.bo.DdlTableBO; import com.vci.ubcs.ddl.bo.DdlTableInDataBaseBO; import com.vci.ubcs.ddl.processor.ddl.DdlMapperProcessStrategy; import com.vci.ubcs.ddl.processor.ddl.DdlMapperProcessor; import com.vci.ubcs.ddl.processor.dll.DllMapperProcessor; import com.vci.ubcs.ddl.processor.dll.DllMapperProcessorStrategy; import com.vci.ubcs.ddl.properties.DdlExportWordFieldProperties; import com.vci.ubcs.ddl.properties.DdlPropertise; import com.vci.ubcs.ddl.service.IDdlService; import com.vci.ubcs.omd.cache.OmdBtmTypeCache; import com.vci.ubcs.omd.dto.OmdBtmTypeDTO; import com.vci.ubcs.omd.entity.OsModifyAttributeInfoDO; import com.vci.ubcs.omd.vo.OmdBtmTypeAttributeVO; import com.vci.ubcs.omd.vo.OmdBtmTypeVO; import com.vci.ubcs.omd.vo.OsLinkTypeAttributeVO; import com.vci.ubcs.omd.vo.OsLinkTypeVO; import com.vci.ubcs.starter.exception.VciBaseException; import com.vci.ubcs.starter.web.util.VciBaseUtil; import org.apache.commons.lang3.StringUtils; import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.BeanUtil; import org.springblade.core.tool.utils.Func; import org.springblade.core.tool.utils.StringPool; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.util.*; import java.util.stream.Collectors; /** * Description: 数据库表操作服务 * * @author LiHang * @date 2023/4/24 */ @Service public class DdlServiceImpl implements IDdlService { /** * 相应的配置 */ @Autowired private DdlPropertise ddlProperties; /** * word导出的时候的域字段映射 */ @Autowired private DdlExportWordFieldProperties wordFieldProperties; /** * ddl数据操作服务 */ private final DdlMapperProcessor ddlMapper = DdlMapperProcessStrategy.getProcessor(); /** * dll数据操作服务 */ private final DllMapperProcessor dllMapper = DllMapperProcessorStrategy.getProcessor(); /** * 表名前缀 */ private final String TABLE_PREFIX = "PL"; /** * 校验业务类型的数据库表中是否有数据 * * @param pkBtmType 业务类型的主键 * @return true表示有数据,false表示没有数据 * @throws VciBaseException 参数为空或者查询出错的时候会抛出异常 */ @Override public boolean checkTableHasData(String pkBtmType) throws VciBaseException { return checkTableHasDataByTableName(getTableNameByBtmTypeOid(pkBtmType)); } /** * 根据业务类型或者链接类型的主键获取数据库表格的名称 * * @param pkBtmType 业务类型或者链接类型的主键 * @return 数据库表名称 */ @Override public String getTableNameByBtmTypeOid(String pkBtmType) { VciBaseUtil.alertNotNull(pkBtmType, "业务类型或者链接类型的主键"); OmdBtmTypeVO btmType = OmdBtmTypeCache.getDetail(pkBtmType); String tableName = ""; if (btmType == null || StringUtils.isBlank(btmType.getOid())) { /*OsLinkTypeDO linkTypeDO = linkTypeDOMapper.selectByPrimaryKey(pkBtmType.trim()); if(linkTypeDO == null || StringUtils.isBlank(linkTypeDO.getOid()) ){ throw new com.vci.starter.web.exception.VciBaseException("不是业务类型,也不是链接类型,请查证"); }else{ tableName = linkTypeService.getTableName(linkTypeDO.getId()); }*/ } else { tableName = btmType.getTableName(); } return tableName; } /** * 根据业务类型获取链接类型的英文名称获取数据库表格的名称 * * @param id 业务类型获取链接类型的英文名称 * @return 数据库表名称 */ @Override public String getTableNameByBtmTypeId(String id) { VciBaseUtil.alertNotNull(id, "业务类型或者链接类型的英文名称"); List btmTypeList = OmdBtmTypeCache.selectByIdCollection(VciBaseUtil.str2List(id)); String tableName = ""; if (CollectionUtils.isEmpty(btmTypeList)) { /*List linkTypeDOList = linkTypeDOMapper.selectByIdCollection(VciBaseUtil.str2List(id)); if(CollectionUtils.isEmpty(linkTypeDOList)){ throw new com.vci.starter.web.exception.VciBaseException("不是业务类型,也不是链接类型,请查证"); }else{ tableName = linkTypeService.getTableName(linkTypeDOList.get(0).getId()); }*/ } else { tableName = btmTypeList.get(0).getTableName(); } return tableName; } /** * 校验业务类型的数据库表中是否有数据 * * @param id 业务类型的英文名称 * @return true表示有数据,false表示没有数据 * @throws VciBaseException 参数为空或者查询出错的时候会抛出异常 */ @Override public boolean checkTableHasDataById(String id) throws VciBaseException { return checkTableHasDataByTableName(getTableNameByBtmTypeId(id)); } /** * 批量将业务类型创建数据库表 * * @param pkBtmTypes 业务类型的主键 * @throws VciBaseException 参数为空或者创建表出现了错误的时候会抛出异常 */ @Override public void createDbTables(String pkBtmTypes) throws VciBaseException { VciBaseUtil.alertNotNull(pkBtmTypes, "业务类型/链接类型的主键"); createDbTablesByOidCollection(VciBaseUtil.str2List(pkBtmTypes)); } /** * 批量将业务类型创建数据库表 * * @param oidCollection 业务类型的主键集合 * @throws VciBaseException 参数为空或者创建表出现了错误的时候会抛出异常 */ @Override public void createDbTablesByOidCollection(Collection oidCollection) throws VciBaseException { VciBaseUtil.alertCollectionNotNull("业务类型/链接类型的主键集合", oidCollection); List btmTypeVOList = OmdBtmTypeCache.listBtmTypeByOidCollection(oidCollection); // List linkTypeVOList = linkTypeService.listLinkTypeByOidCollection(oidCollection); if (!CollectionUtils.isEmpty(btmTypeVOList)) { //说明是业务类型 btmTypeVOList.forEach(this::createDbTableForBtm); } //链接类型 /*if(!CollectionUtils.isEmpty(linkTypeVOList)){ linkTypeVOList.stream().forEach( s -> { createDbTableForLink(s); }); }*/ } /** * 创建业务类型的表格 * * @param btmTypeVO 业务类型的显示对象 * @throws VciBaseException 执行出错的时候会抛出异常 */ private void createDbTableForBtm(OmdBtmTypeVO btmTypeVO) throws VciBaseException { VciBaseUtil.alertNotNull(btmTypeVO, "要创建表格所属的业务类型", btmTypeVO.getTableName(), "业务类型的表格名称"); if (btmTypeVO.isViewFlag() && StringUtils.isNotBlank(btmTypeVO.getViewCreateSql())) { //说明是视图 this.createViewBySql("create or replace " + btmTypeVO.getTableName() + " as " + btmTypeVO.getViewCreateSql()); } else { String tableName = btmTypeVO.getTableName(); if (!checkTableExistByTableName(tableName)) { String attributeSql = dllMapper.getCreateSqlByAttributeForBtm(btmTypeVO.getAttributes()); dllMapper.createTableBySql(tableName, attributeSql); if (StringUtils.isNotBlank(btmTypeVO.getName())) { dllMapper.commentTable(tableName, btmTypeVO.getName()); } btmTypeVO.getAttributes().stream().forEach(s -> { dllMapper.commentColumnTable(tableName, s.getId(), s.getName()); }); } } } /** * 批量将业务类型创建数据库表 * * @param ids 业务类型的英文名称 * @throws VciBaseException 参数为空或者创建表出现了错误的时候会抛出异常 */ @Override public void createDbTablesById(String ids) throws VciBaseException { VciBaseUtil.alertNotNull(ids, "业务类型/链接类型的英文集合"); List btmTypeVOList = OmdBtmTypeCache.selectByIdCollection(VciBaseUtil.str2List(ids)); // List linkTypeVOList = linkTypeService.listLinkTypeByIdCollection(VciBaseUtil.str2List(ids)); if (!CollectionUtils.isEmpty(btmTypeVOList)) { //说明是业务类型 btmTypeVOList.forEach(this::createDbTableForBtm); } /*//试试链接类型 if(!CollectionUtils.isEmpty(linkTypeVOList)){ //的确是链接类型 linkTypeVOList.stream().forEach( s -> { createDbTableForLink(s); }); }*/ } /** * 修改业务类型中的属性字段的长度,注意在执行这个方法时就会将以前的事务提交。 * * @param modifyLengthAttrVOList 需要修改的属性对象 * @throws VciBaseException 执行出错的时候会抛出异常 */ @Override public void changeColumnForBtm(List modifyLengthAttrVOList) throws VciBaseException { VciBaseUtil.alertCollectionNotNull("要修改长度的属性集", modifyLengthAttrVOList); Map> btmTypeHasAttributeVOMap = modifyLengthAttrVOList.stream().collect(Collectors.groupingBy(OmdBtmTypeAttributeVO::getPkBtmType)); btmTypeHasAttributeVOMap.forEach((k, v) -> { OmdBtmTypeVO btmTypeVO = OmdBtmTypeCache.getDetail(k); if (btmTypeVO == null || StringUtils.isBlank(btmTypeVO.getOid())) { throw new VciBaseException("要修改属性列长度的业务类型不存在"); } if (!isCompatibilityTable(btmTypeVO.getId(), null)) { //要看看这个链接类型对应的数据库表是否存在 String tableName = btmTypeVO.getTableName(); if (checkTableExistByTableName(tableName)) { changeColumnsForTable(tableName, v); } else { createDbTableForBtm(btmTypeVO); } changeColumnsForTable(btmTypeVO.getTableName(), v); } }); } /** * 执行SQL语句的修改 * * @param tableName 表格的名称 * @param attributeVOList 要添加的属性字段 */ private void changeColumnsForTable(String tableName, List attributeVOList) { String attributeSql = dllMapper.getCreateSqlByAttributeForBtm(attributeVOList); //先判断表格是否存在 boolean tableExist = false; try { ddlMapper.countAll(tableName); tableExist = true; } catch (Throwable e) { //说明表格就不存在 createDbTables(attributeVOList.get(0).getPkBtmType()); } if (tableExist) { ddlMapper.modifyTableBySqlBase(tableName, attributeSql); commentColumnsForTable(tableName, attributeVOList); } } /** * 给表格的字段添加注释 * * @param tableName 表格名称 * @param attributeVOList 属性对象列表 */ private void commentColumnsForTable(String tableName, List attributeVOList) { if (StringUtils.isNotBlank(tableName) && !CollectionUtils.isEmpty(attributeVOList)) { attributeVOList.stream().forEach(s -> { ddlMapper.commentColumnTable(tableName, s.getId(), s.getName()); }); } } /** * 修改链接类型中的属性字段的长度,注意在执行这个方法时就会将以前的事务提交。 * * @param modifyLengthAttrDOListForLinkType 需要修改的属性对象 * @throws VciBaseException 执行出错的时候会抛出异常 */ @Override public void changeColumnForLink(List modifyLengthAttrDOListForLinkType) throws VciBaseException { } /** * 添加属性字段到业务类型中,注意在执行这个方法时就会将以前的事务提交。 * * @param addAttrDOList 需要添加的属性对象 * @throws VciBaseException 执行出错的时候会抛出异常 */ @Override public void addColumn2TableForBtm(List addAttrDOList) throws VciBaseException { VciBaseUtil.alertCollectionNotNull("要添加到数据库表中的属性集", addAttrDOList); Map> btmTypeHasAttributeVOMap = addAttrDOList.stream().collect(Collectors.groupingBy(OmdBtmTypeAttributeVO::getPkBtmType)); btmTypeHasAttributeVOMap.forEach((k, v) -> { OmdBtmTypeVO btmTypeVO = OmdBtmTypeCache.getDetail(k); if (btmTypeVO == null || StringUtils.isBlank(btmTypeVO.getOid())) { throw new VciBaseException("要修改属性列长度的业务类型不存在"); } if (!isCompatibilityTable(btmTypeVO.getId(), null)) { addColumnForTable(btmTypeVO.getTableName(), v); } }); } /** * 添加字段到表格中 * * @param tableName 表格名称 * @param attributeVOList 属性的显示对象 * @throws VciBaseException 执行或者获取sql语句的时候出现错误会抛出异常 */ private void addColumnForTable(String tableName, List attributeVOList) throws VciBaseException{ String attributeSql = dllMapper.getCreateSqlByAttributeForBtm(attributeVOList); //先判断表格是否存在 if (!checkTableExistByTableName(tableName)) { OmdBtmTypeAttributeVO attributeVO = attributeVOList.get(0); createDbTables(attributeVO.getPkBtmType()); } else { ddlMapper.addColumn2TableBySql(tableName, attributeSql); commentColumnsForTable(tableName, attributeVOList); } } /** * 添加属性字段到链接类型中,注意在执行这个方法时就会将以前的事务提交。 * * @param addAttrDOListForLinkType 需要添加的属性对象 * @throws VciBaseException 执行出错的时候会抛出异常 */ @Override public void addColumn2TableForLink(List addAttrDOListForLinkType) throws VciBaseException { } /** * 判断表中是否有数据 * * @param tableName 表格的名称 * @return true表示有数据,false表示没有数据,或者这个表格不存在的时候抛出异常 * @throws VciBaseException 参数错误的时候抛出异常 */ @Override public boolean checkTableHasDataByTableName(String tableName) throws VciBaseException { try { int tableCount = ddlMapper.countAll(tableName); if (tableCount > 0) { return true; } } catch (Throwable e) { throw new VciBaseException("统计某个表是否含有数据出错,可能表不存在"); } return false; } /** * 创建视图 * * @param viewCreateSql 视图的SQL语句 * @throws VciBaseException 参数错误或者执行错误的时候会抛出异常,执行错误主要包括SQL语句错误,没有权限等 */ @Override public void createViewBySql(String viewCreateSql) throws VciBaseException { VciBaseUtil.alertNotNull(viewCreateSql, "视图的SQL"); ddlMapper.createViewBySql(viewCreateSql); } /** * 删除表格或者视图 * * @param tableName 表格名称或者视图名称 * @throws VciBaseException 参数错误或者执行错误的时候会抛出异常 */ @Override public void dropTableByName(String tableName) throws VciBaseException { VciBaseUtil.alertNotNull(tableName, "要删除的表的名称"); ddlMapper.dropTable(tableName); } /** * 删除表格的某一列 * * @param tableName 表格名称 * @param columnName 列的名称 */ @Override public void dropColumnByName(String tableName, String columnName) { VciBaseUtil.alertNotNull(tableName, "要删除的表的名称", columnName, "要删除的表字段名称"); ddlMapper.dropTableColumn(tableName, columnName); } /** * 校验业务类型或者链接类型的对应的表格是否存在 * * @param pkBtmType 业务类型或者链接类型的表格 * @return true表示存在,false表示不存在 */ @Override public boolean checkTableExist(String pkBtmType) { return checkTableExistByTableName(getTableNameByBtmTypeOid(pkBtmType)); } /** * 根据表格的名称判断表格是否存在 * * @param tableName 表格名称 * @return rue表示存在,false表示不存在 */ @Override public boolean checkTableExistByTableName(String tableName) { return ddlMapper.checkTableExist(tableName) > 0; } /** * 校验业务类型或者链接类型所对应的表格是否存在 * * @param id 业务类型或者链接类型的英文名称 * @return true表示存在,false表示不存在 */ @Override public boolean checkTableExistById(String id) { return checkTableExistByTableName(getTableNameByBtmTypeId(id)); } /** * 获取数据库和业务类型中的不同的地方 * * @param btmTypeVOList 业务类型对象,有属性时需要包含属性 * @param linkTypeVOList 链接类型对象,有属性时需要包含属性 * @return 不同的地方,每一个业务类型或者链接类型一条数据 */ @Override public List checkDifferent(List btmTypeVOList, List linkTypeVOList) throws VciBaseException { return null; } /** * 清理业务类型中和数据库里不一样的 * * @param differentAttributeList 不同的属性的列表 * @throws VciBaseException 参数为空或者执行出错的时候会抛出异常 */ @Override public void reflexDifferent(List differentAttributeList) throws VciBaseException { } /** * 获取数据库中所有的表格 * * @return 表格的名称,全是大写 */ @Override public List listAllTableName() { return ddlMapper.selectAllTableName(); } /** * 查询数据库中的表格信息 * * @param tableNamesCollections 数据库表名集合 * @return 在数据库中的信息 * @throws VciBaseException 参数为空或者数据库表不存在的时候会抛出异常 */ @Override public List listTableInfoInDB(Collection tableNamesCollections) throws VciBaseException { VciBaseUtil.alertCollectionNotNull("数据库表名称不能为空", tableNamesCollections); List tableBOList = new ArrayList<>(); tableNamesCollections.stream().forEach(s -> { tableBOList.add(ddlMapper.selectTableComment(s)); }); return tableBOList; } /** * 导出数据库中的表格信息到excel文件 * * @param tableNamesCollections 表格名称的集合 * @param merge 合并表格名称 * @return excel的文件名称 * @throws VciBaseException 蚕食为空或者数据库表不存在的时候会抛出异常 */ @Override public String exportDataBase2File(Collection tableNamesCollections, boolean merge) throws VciBaseException { return null; } /** * 获取存储文件所需要的临时文件夹,文件夹上已经包含了 * * @return 文件夹的地址,如果配置文件没有配置,则默认返回当前项目所在的文件夹 */ @Override public String getTempFolder() { return null; } /** * 导出数据库中的表格信息到word文件中 * * @param tableNamesCollections 表格名称的集合 * @return word的文件名称 * @throws VciBaseException 蚕食为空或者数据库表不存在的时候会抛出异常 */ @Override public String exportDataBase2Word(List tableNamesCollections) throws VciBaseException { return null; } /** * 拷贝数据到word模板中 * * @param tableDataBO 要写入的数据 * @return word 文件路径 */ @Override public String writeDataToWord(WordMergeStartTableDataBO tableDataBO) { return null; } /** * 判断是否为兼容性的表,这些表不应该被创建和修改 * * @param btmTypeId 业务类型的英文名称 * @param linkTypeId 业务类型的中文名称 * @return true 表示为兼容性的表,用户,角色,部门,权限这些 */ @Override public boolean isCompatibilityTable(String btmTypeId, String linkTypeId) { return false; } /** * 业务类型数据库新增或修改表 * * @param dto 业务类型传输对象 * @return 执行结果 */ @Override public R submitBtmType(OmdBtmTypeDTO dto) { VciBaseUtil.alertNotNull(dto, "业务类型", dto.getAttributesDTOList(), "业务类型属性"); OmdBtmTypeVO btmTypeVO = Objects.requireNonNull(BeanUtil.copy(dto, OmdBtmTypeVO.class)); if (Func.isNotBlank(dto.getTableName())) { checkModifyOrCreateTable(btmTypeVO); } else { if (checkTableExistById(dto.getId())) { String tableName = getTableNameByBtmTypeId(dto.getId()); btmTypeVO.setTableName(tableName); checkModifyOrCreateTable(btmTypeVO); } else { String tableName = TABLE_PREFIX + StringPool.UNDERSCORE + dto.getDomain().toUpperCase(Locale.ROOT) + StringPool.UNDERSCORE + dto.getId().toUpperCase(Locale.ROOT); btmTypeVO.setTableName(tableName); createDbTableForBtm(btmTypeVO); } } return R.success("000000"); } /** * 检查业务类型的表是否存在,如果存在则比较差别进行修改,不存在则创建 * * @param btmTypeVO 业务类型 */ private void checkModifyOrCreateTable(OmdBtmTypeVO btmTypeVO) { if (checkTableExistByTableName(btmTypeVO.getTableName())) { // 表已存在,校验属性 List vos = new ArrayList<>(); vos.add(btmTypeVO); List differentAttributeList = checkDifferent(vos, null); if (CollectionUtils.isEmpty(differentAttributeList)) { // 可以直接删除再创建 dropTableByName(btmTypeVO.getTableName()); createDbTableForBtm(btmTypeVO); } else { // TODO: 修改的暂时还没做 } } else { createDbTableForBtm(btmTypeVO); } } /** * 按表名获取表信息 * * @param tableName 表名 * @return 表信息 */ @Override public DdlTableBO getTableColumnByTableName(String tableName) { VciBaseUtil.alertNotNull(tableName,"表名"); DdlTableBO tableBO = getTableInfoByTableName(tableName); List columnInfo = selectTableColumnInfo(tableName); tableBO.setColumns(columnInfo); return tableBO; } /** * 查询数据库中表格的字段信息 * * @param tableName 表格的名称 * @return 数据库表的字段信息 */ private List selectTableColumnInfo(String tableName) { VciBaseUtil.alertNotNull(tableName, "表格名称"); return ddlMapper.selectTableColumnInfo(tableName); } /** * 表名获取表信息 * @param tableName 表名 * @return 表信息 */ private DdlTableBO getTableInfoByTableName(String tableName){ VciBaseUtil.alertNotNull(tableName, "表格名称"); return ddlMapper.selectTableComment(tableName); } /** * 获取所有表信息 * * @return 表信息集合 */ @Override public List getAllTableInfo() { List allTableName = listAllTableName(); if (!CollectionUtils.isEmpty(allTableName)) { List allTableBO = listTableInfoInDB(allTableName); allTableBO.forEach(table -> { table.setColumns(selectTableColumnInfo(table.getTableName())); }); return allTableBO; } return new ArrayList<>(); } }