田源
2023-05-09 d2570148ec3884de3af721bd99c4b7acbbdee075
Source/UBCS/ubcs-service/ubcs-ddl/src/main/java/com/vci/ubcs/ddl/service/impl/DdlServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1132 @@
package com.vci.ubcs.ddl.service.impl;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.nacos.shaded.com.google.protobuf.ServiceException;
import com.vci.ubcs.ddl.bo.DdlTableBO;
import com.vci.ubcs.ddl.bo.DdlTableInDataBaseBO;
import com.vci.ubcs.ddl.enums.BusinessTypeEnum;
import com.vci.ubcs.ddl.enums.ModifyTableTaskEnum;
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.DdlPropertise;
import com.vci.ubcs.ddl.service.IDdlService;
import com.vci.ubcs.omd.cache.BtmTypeCache;
import com.vci.ubcs.omd.constant.BtmTypeFieldConstant;
import com.vci.ubcs.omd.constant.BtmTypeLcStatusConstant;
import com.vci.ubcs.omd.dto.BtmAndLinkTypeDdlDTO;
import com.vci.ubcs.omd.entity.ModifyAttributeInfo;
import com.vci.ubcs.omd.vo.*;
import com.vci.ubcs.starter.exception.VciBaseException;
import com.vci.ubcs.starter.web.enumpck.BooleanEnum;
import com.vci.ubcs.starter.web.enumpck.VciFieldTypeEnum;
import com.vci.ubcs.starter.web.util.VciBaseUtil;
import org.springblade.core.secure.utils.AuthUtil;
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 javax.validation.constraints.NotNull;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
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 static final String YES = "Y";
   private static final String NO = "N";
   private final Map<String, BtmTypeVO> idBtmMap = new ConcurrentHashMap<>();
   private final Map<String, LinkTypeVO> idLinkMap = new ConcurrentHashMap<>();
   private void putBtm(@NotNull BtmTypeVO... voList) throws ServiceException {
      String collect = Arrays.stream(voList).map(BtmTypeVO::getId).filter(idBtmMap::containsKey).collect(Collectors.joining(","));
      if (StringUtils.isBlank(collect)) {
         Arrays.stream(voList).forEach(vo -> {
            idBtmMap.put(vo.getId(), vo);
         });
      } else {
         throw new ServiceException("业务类型:[" + collect + "]正在被其他用户操作");
      }
   }
   private void putLink(@NotNull LinkTypeVO... voList) throws ServiceException {
      String collect = Arrays.stream(voList).map(LinkTypeVO::getId).filter(idLinkMap::containsKey).collect(Collectors.joining(","));
      if (StringUtils.isBlank(collect)) {
         Arrays.stream(voList).forEach(vo -> {
            idLinkMap.put(vo.getId(), vo);
         });
      } else {
         throw new ServiceException("链接类型:[" + collect + "]正在被其他用户操作");
      }
   }
   private void removeBtm(@NotNull BtmTypeVO... btmTypeVO) throws ServiceException {
      if (Arrays.stream(btmTypeVO).allMatch(s -> idBtmMap.containsKey(s.getId()))) {
         for (BtmTypeVO vo : btmTypeVO) {
            idBtmMap.remove(vo.getId());
         }
      } else {
         throw new ServiceException("解锁对象不存在");
      }
   }
   private void removeLink(@NotNull LinkTypeVO... linkTypeVO) throws ServiceException {
      if (Arrays.stream(linkTypeVO).allMatch(s -> idLinkMap.containsKey(s.getId()))) {
         for (LinkTypeVO vo : linkTypeVO) {
            idLinkMap.remove(vo.getId());
         }
      } else {
         throw new ServiceException("解锁对象不存在");
      }
   }
   /**
    * æ ¡éªŒä¸šåŠ¡ç±»åž‹çš„æ•°æ®åº“è¡¨ä¸­æ˜¯å¦æœ‰æ•°æ®
    *
    * @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, "业务类型或者链接类型的主键");
      BtmTypeVO btmType = BtmTypeCache.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<BtmTypeVO> btmTypeList = BtmTypeCache.selectByIdCollection(VciBaseUtil.str2List(id));
      String tableName = "";
      if (CollectionUtils.isEmpty(btmTypeList)) {
         /*List<OsLinkTypeDO> 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<String> oidCollection) throws VciBaseException {
      VciBaseUtil.alertNotNull("业务类型/链接类型的主键集合", oidCollection);
      List<BtmTypeVO> btmTypeVOList = BtmTypeCache.listBtmTypeByOidCollection(oidCollection);
//      List<OsLinkTypeVO> 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(BtmTypeVO 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 = getCreateSqlByAttributeForBtm(btmTypeVO.getAttributes());
            dllMapper.createTableBySql(tableName, attributeSql);
            if (StringUtils.isNotBlank(btmTypeVO.getName())) {
               dllMapper.commentTable(tableName, btmTypeVO.getName());
            }
            btmTypeVO.getAttributes().forEach(s -> {
               dllMapper.commentColumnTable(tableName, s.getId(), s.getName());
            });
         }
      }
   }
   /**
    * èŽ·å–åˆ›å»ºçš„sql语句中属性部分
    *
    * @param attributeVOList å±žæ€§çš„立碑
    * @return sql语句
    */
   @Override
   public String getCreateSqlByAttributeForBtm(List<BtmTypeAttributeVO> attributeVOList) {
      StringBuilder sb = new StringBuilder();
      attributeVOList.forEach(a -> {
         sb.append(a.getId()).append(StringPool.SPACE);
         VciFieldTypeEnum fieldTypeEnum = VciFieldTypeEnum.forValue(a.getAttrDataType());
         sb.append(dllMapper.getColumnTypeSql(fieldTypeEnum, a));
      });
      return sb.substring(0, sb.lastIndexOf(","));
   }
   /**
    * æ‰¹é‡å°†ä¸šåŠ¡ç±»åž‹åˆ›å»ºæ•°æ®åº“è¡¨
    *
    * @param ids ä¸šåŠ¡ç±»åž‹çš„è‹±æ–‡åç§°
    * @throws VciBaseException å‚数为空或者创建表出现了错误的时候会抛出异常
    */
   @Override
   public void createDbTablesById(String ids) throws VciBaseException {
      VciBaseUtil.alertNotNull(ids, "业务类型/链接类型的英文集合");
      List<BtmTypeVO> btmTypeVOList = BtmTypeCache.selectByIdCollection(VciBaseUtil.str2List(ids));
//      List<OsLinkTypeVO> 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<BtmTypeAttributeVO> modifyLengthAttrVOList) throws VciBaseException {
      VciBaseUtil.alertNotNull("要修改长度的属性集", modifyLengthAttrVOList);
      Map<String, List<BtmTypeAttributeVO>> btmTypeHasAttributeVOMap = modifyLengthAttrVOList.stream().collect(Collectors.groupingBy(BtmTypeAttributeVO::getPkBtmType));
      btmTypeHasAttributeVOMap.forEach((k, v) -> {
         BtmTypeVO btmTypeVO = BtmTypeCache.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<BtmTypeAttributeVO> attributeVOList) {
      String attributeSql = 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<BtmTypeAttributeVO> attributeVOList) {
      if (StringUtils.isNotBlank(tableName) && !CollectionUtils.isEmpty(attributeVOList)) {
         attributeVOList.forEach(s -> {
            ddlMapper.commentColumnTable(tableName, s.getId(), s.getName());
         });
      }
   }
   /**
    * ä¿®æ”¹é“¾æŽ¥ç±»åž‹ä¸­çš„属性字段的长度,注意在执行这个方法时就会将以前的事务提交。
    *
    * @param modifyLengthAttrDOListForLinkType éœ€è¦ä¿®æ”¹çš„属性对象
    * @throws VciBaseException æ‰§è¡Œå‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
    */
   @Override
   public void changeColumnForLink(List<LinkTypeAttributeVO> modifyLengthAttrDOListForLinkType) throws VciBaseException {
   }
   /**
    * æ·»åŠ å±žæ€§å­—æ®µåˆ°ä¸šåŠ¡ç±»åž‹ä¸­ï¼Œæ³¨æ„åœ¨æ‰§è¡Œè¿™ä¸ªæ–¹æ³•æ—¶å°±ä¼šå°†ä»¥å‰çš„äº‹åŠ¡æäº¤ã€‚
    *
    * @param addAttrDOList éœ€è¦æ·»åŠ çš„å±žæ€§å¯¹è±¡
    * @throws VciBaseException æ‰§è¡Œå‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
    */
   @Override
   public void addColumn2TableForBtm(List<BtmTypeAttributeVO> addAttrDOList) throws VciBaseException {
      VciBaseUtil.alertNotNull("要添加到数据库表中的属性集", addAttrDOList);
      Map<String, List<BtmTypeAttributeVO>> btmTypeHasAttributeMap = addAttrDOList.stream().collect(Collectors.groupingBy(BtmTypeAttributeVO::getPkBtmType));
      btmTypeHasAttributeMap.forEach((k, v) -> {
         BtmTypeVO btmTypeVO = BtmTypeCache.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<BtmTypeAttributeVO> attributeVOList) {
      String attributeSql = getCreateSqlByAttributeForBtm(attributeVOList);
      //先判断表格是否存在
      if (!checkTableExistByTableName(tableName)) {
         BtmTypeAttributeVO attributeVO = attributeVOList.get(0);
         createDbTables(attributeVO.getPkBtmType());
      } else {
         ddlMapper.addColumn2TableBySql(tableName, attributeSql);
         commentColumnsForTable(tableName, attributeVOList);
      }
   }
   /**
    * æ·»åŠ å±žæ€§å­—æ®µåˆ°é“¾æŽ¥ç±»åž‹ä¸­ï¼Œæ³¨æ„åœ¨æ‰§è¡Œè¿™ä¸ªæ–¹æ³•æ—¶å°±ä¼šå°†ä»¥å‰çš„äº‹åŠ¡æäº¤ã€‚
    *
    * @param addAttrDOListForLinkType éœ€è¦æ·»åŠ çš„å±žæ€§å¯¹è±¡
    * @throws VciBaseException æ‰§è¡Œå‡ºé”™çš„æ—¶å€™ä¼šæŠ›å‡ºå¼‚常
    */
   @Override
   public void addColumn2TableForLink(List<LinkTypeAttributeVO> addAttrDOListForLinkType) throws VciBaseException {
      VciBaseUtil.alertNotNull("要添加到数据库表中属性集",addAttrDOListForLinkType);
      Map<String, List<LinkTypeAttributeVO>> linkTypeHasAttributeVOMap = addAttrDOListForLinkType.stream().collect(Collectors.groupingBy(LinkTypeAttributeVO::getPkLinkType));
      linkTypeHasAttributeVOMap.forEach((k,v) -> {
      });
   }
   /**
    * åˆ¤æ–­è¡¨ä¸­æ˜¯å¦æœ‰æ•°æ®
    *
    * @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<ModifyAttributeInfo> checkDifferent(List<BtmTypeVO> btmTypeVOList, List<LinkTypeVO> linkTypeVOList) throws VciBaseException {
      if (CollectionUtils.isEmpty(btmTypeVOList) && CollectionUtils.isEmpty(linkTypeVOList)) {
         throw new VciBaseException("要检查的业务类型和链接类型为空");
      }
      List<ModifyAttributeInfo> modifyAttributeInfoList = new ArrayList<>();
      if (!CollectionUtils.isEmpty(btmTypeVOList)) {
         modifyAttributeInfoList.addAll(checkBtmType(btmTypeVOList));
      }
      if (!CollectionUtils.isEmpty(linkTypeVOList)) {
         modifyAttributeInfoList.addAll(checkLinkType(linkTypeVOList));
      }
      if (CollectionUtils.isEmpty(modifyAttributeInfoList)) {
         reflexDifferent(modifyAttributeInfoList, btmTypeVOList, linkTypeVOList);
      }
      return modifyAttributeInfoList;
   }
   /**
    * æ£€æŸ¥ä¸šåŠ¡ç±»åž‹
    *
    * @param btmTypeVOList ä¸šåŠ¡ç±»åž‹
    * @return æ£€æŸ¥ç»“æžœ
    */
   private List<ModifyAttributeInfo> checkBtmType(List<BtmTypeVO> btmTypeVOList) {
      List<ModifyAttributeInfo> modifyAttributeInfoDOList = new ArrayList<>();
      btmTypeVOList.stream().filter(s -> !isCompatibilityTable(s.getId(),null)).forEach(btm -> {
         ModifyAttributeInfo modifyAttributeInfo = new ModifyAttributeInfo();
         modifyAttributeInfo.setId(btm.getId());
         modifyAttributeInfo.setName(btm.getName());
         modifyAttributeInfo.setTableName(btm.getTableName());
         modifyAttributeInfo.setBusinessType(BusinessTypeEnum.BTM.getValue());
         // 1. è§†å›¾å’Œæ–°å»ºçš„,直接创建,记录创建历史
         if (btm.isViewFlag() || !checkTableExistByTableName(btm.getTableName())){
            modifyAttributeInfo.setTaskName(ModifyTableTaskEnum.CREATE.getValue());
            modifyAttributeInfo.setModifyColumnReason(ModifyTableTaskEnum.CREATE.getValue());
         }else {
            VciBaseUtil.alertNotNull(btm.getAttributes(),"业务类型" + btm.getId() + "的属性");
            List<DdlTableInDataBaseBO> columnDataInTable = selectTableColumnInfo(btm.getTableName());
            if (CollectionUtils.isEmpty(columnDataInTable)){
               modifyAttributeInfo.setAddAttributes(btm.getAttributes().stream().map(s -> s.getId().toLowerCase().trim()).collect(Collectors.joining(",")));
               modifyAttributeInfo.setTaskName(ModifyTableTaskEnum.EDIT.getValue());
               modifyAttributeInfo.setModifyColumnReason(ModifyTableTaskEnum.CREATE.getValue());
            }else {
               // 2. å­˜åœ¨çš„æ‰åˆ¤æ–­ï¼Œåˆ†æ–°å¢žå±žæ€§ã€å±žæ€§æ›´æ”¹ã€å±žæ€§åˆ é™¤åˆ†åˆ«æ“ä½œ
               // 3. å±žæ€§æ“ä½œä¸­ç‰¹åˆ«åˆ¤æ–­[是否控制版本][是否控制密级][是否控制生命周期]来添加对应属性
               Map<String, DdlTableInDataBaseBO> tableColumMap = columnDataInTable.stream().collect(Collectors.toMap(t -> t.getId().toLowerCase().trim(), k -> k));
               Map<String, BtmTypeAttributeVO> attributeMap = btm.getAttributes().stream().collect(Collectors.toMap(t -> t.getId().toLowerCase().trim(), k -> k));
               List<String> addList = new ArrayList<>();
               List<String> editList = new ArrayList<>();
               List<String> deleteList = new ArrayList<>();
               List<String> beforeList = new ArrayList<>();
               attributeMap.forEach((k,v) -> {
                  String attributeLowId = k.toLowerCase();
                  if (!checkIsDefaultColumn(attributeLowId)) {
                     if (tableColumMap.containsKey(k)) {
                        //说明以前也有,那就看是否需要修改
                        DdlTableInDataBaseBO columnInDB = tableColumMap.get(k);
                        if (columnInDB.getAttributeLength() == null) {
                           columnInDB.setAttributeLength(0);
                        }
                        boolean needEdit = false;
                        if (!v.getName().equalsIgnoreCase(columnInDB.getName())) {
                           //说明需要修改
                           needEdit = true;
                        }
                        if (needEdit || checkNeedEditAttr(v, columnInDB)) {
                           editList.add(v.getId());
                           beforeList.add(columnInDB.getId() + StringPool.SPACE + columnInDB.getAttrDataType() + "(" + columnInDB.getAttributeLength() + ")" + StringPool.SPACE + columnInDB.getNullableFlag()
                              + StringPool.SPACE + columnInDB.getPrecisionLength() + StringPool.SPACE + columnInDB.getScaleLength() + StringPool.SPACE + columnInDB.getName());
                        }
                     } else {
                        addList.add(v.getId());
                     }
                  } else {
                     //针对默认属性,如果以前没有,现在有可以添加,如果以前
                     if (!tableColumMap.containsKey(k)) {
                        boolean needAddNewField = false;
                        if (!BtmTypeLcStatusConstant.EMTYPE_LIFE_CYCLE.equalsIgnoreCase(btm.getLifeCycleId()) && BtmTypeFieldConstant.LIFECYCLE_MANAGE_FIELD_MAP.containsKey(attributeLowId)) {
                           needAddNewField = true;
                        }
                        if (StringUtils.isNotBlank(btm.getRevisionRuleId()) && BtmTypeFieldConstant.REVISION_MANAGE_FIELD_MAP.containsKey(attributeLowId)) {
                           needAddNewField = true;
                        }
                        if (btm.isSecretFlag() && BtmTypeFieldConstant.SECRET_MANAGE_FIELD_MAP.containsKey(attributeLowId)) {
                           needAddNewField = true;
                        }
                        if (needAddNewField) {
                           addList.add(v.getId());
                        }
                     }
                  }
               });
               tableColumMap.forEach((k, v) -> {
                  if (!attributeMap.containsKey(k)) {
                     deleteList.add(k);
                  }
               });
               modifyAttributeInfo.setOrderModifyUserName(AuthUtil.getUserAccount());
               modifyAttributeInfo.setOrderModifyDate(new Date());
               modifyAttributeInfo.setModifyColumnReason(ModifyTableTaskEnum.CONSISTENCY_CHECK.getValue());
               modifyAttributeInfo.setTaskName(ModifyTableTaskEnum.CONSISTENCY_CHECK.getValue());
               modifyAttributeInfo.setAddAttributes(String.join(",", addList));
               modifyAttributeInfo.setModifyAttributes(String.join(",", editList));
               modifyAttributeInfo.setDeleteAttributes(String.join(",", deleteList));
               modifyAttributeInfo.setBeforeModifyAttributes(String.join(",", beforeList));
            }
         }
      });
      return modifyAttributeInfoDOList;
   }
   private boolean checkIsDefaultColumn(String attributeLowId) {
      return ((BtmTypeFieldConstant.BASIC_FIELD_MAP.containsKey(attributeLowId)
         && !VciBaseUtil.inArray(new String[]{"id", "name", "description"}, attributeLowId))
         || BtmTypeFieldConstant.LINK_TYPE_FIELD_MAP.containsKey(attributeLowId)
         || BtmTypeFieldConstant.LIFECYCLE_MANAGE_FIELD_MAP.containsKey(attributeLowId)
         || BtmTypeFieldConstant.REVISION_MANAGE_FIELD_MAP.containsKey(attributeLowId)
         || BtmTypeFieldConstant.SECRET_MANAGE_FIELD_MAP.containsKey(attributeLowId));
   }
   /**
    * æ£€æŸ¥é“¾æŽ¥ç±»åž‹
    *
    * @param linkTypeVOList é“¾æŽ¥ç±»åž‹
    * @return æ£€æŸ¥ç»“æžœ
    */
   private List<ModifyAttributeInfo> checkLinkType(List<LinkTypeVO> linkTypeVOList) {
      List<ModifyAttributeInfo> modifyAttributeInfoDOList = new ArrayList<>();
      linkTypeVOList.stream().filter(s -> !isCompatibilityTable(null,s.getId())).forEach(link -> {
            ModifyAttributeInfo modifyAttributeInfo = new ModifyAttributeInfo();
            modifyAttributeInfo.setId(link.getId());
            modifyAttributeInfo.setName(link.getName());
            modifyAttributeInfo.setTableName(link.getTableName());
            modifyAttributeInfo.setBusinessType(BusinessTypeEnum.LINK.getValue());
            // 1. è§†å›¾å’Œæ–°å»ºçš„,直接创建,记录创建历史
            if (!checkTableExistByTableName(link.getTableName())){
               modifyAttributeInfo.setTaskName(ModifyTableTaskEnum.CREATE.getValue());
               modifyAttributeInfo.setModifyColumnReason(ModifyTableTaskEnum.CREATE.getValue());
            }else {
               VciBaseUtil.alertNotNull(link.getAttributes(), "链接类型" + link.getId() + "的属性");
               List<DdlTableInDataBaseBO> columnDataInTable = selectTableColumnInfo(link.getTableName());
               if (CollectionUtils.isEmpty(columnDataInTable)) {
                  modifyAttributeInfo.setAddAttributes(link.getAttributes().stream().map(s -> s.getId().toLowerCase().trim()).collect(Collectors.joining(",")));
                  modifyAttributeInfo.setTaskName(ModifyTableTaskEnum.EDIT.getValue());
                  modifyAttributeInfo.setModifyColumnReason(ModifyTableTaskEnum.CREATE.getValue());
               } else {
                  // 2. å­˜åœ¨çš„æ‰åˆ¤æ–­ï¼Œåˆ†æ–°å¢žå±žæ€§ã€å±žæ€§æ›´æ”¹ã€å±žæ€§åˆ é™¤åˆ†åˆ«æ“ä½œ
                  // 3. å±žæ€§æ“ä½œä¸­ç‰¹åˆ«åˆ¤æ–­[是否控制版本][是否控制密级][是否控制生命周期]来添加对应属性
                  Map<String, DdlTableInDataBaseBO> tableColumMap = columnDataInTable.stream().collect(Collectors.toMap(t -> t.getId().toLowerCase().trim(), k -> k));
                  Map<String, LinkTypeAttributeVO> attributeMap = link.getAttributes().stream().collect(Collectors.toMap(t -> t.getId().toLowerCase().trim(), k -> k));
                  List<String> addList = new ArrayList<>();
                  List<String> editList = new ArrayList<>();
                  List<String> deleteList = new ArrayList<>();
                  List<String> beforeList = new ArrayList<>();
                  attributeMap.forEach((k, v) -> {
                     String attributeLowId = k.toLowerCase();
                     if (!(BtmTypeFieldConstant.LINK_TYPE_FIELD_MAP.containsKey(attributeLowId))) {
                        if (tableColumMap.containsKey(k)) {
                           //说明以前也有,那就看是否需要修改
                           DdlTableInDataBaseBO columnInDB = tableColumMap.get(k);
                           if (columnInDB.getAttributeLength() == null) {
                              columnInDB.setAttributeLength(0);
                           }
                           boolean needEdit = false;
                           if (!v.getName().equalsIgnoreCase(columnInDB.getName())) {
                              //说明需要修改
                              needEdit = true;
                           }
                           BtmTypeAttributeVO btmTypeAttributeVO = new BtmTypeAttributeVO();
                           BeanUtil.copy(v, btmTypeAttributeVO);
                           if (needEdit || checkNeedEditAttr(btmTypeAttributeVO, columnInDB)) {
                              editList.add(v.getId());
                              beforeList.add(columnInDB.getId() + StringPool.SPACE + columnInDB.getAttrDataType() + "(" + columnInDB.getAttributeLength() + ")" + StringPool.SPACE + columnInDB.getNullableFlag()
                                 + StringPool.SPACE + columnInDB.getPrecisionLength() + StringPool.SPACE + columnInDB.getScaleLength() + StringPool.SPACE + columnInDB.getName());
                           }
                        } else {
                           addList.add(v.getId());
                        }
                     } else {
                        //针对默认属性,如果以前没有,现在有可以添加,如果以前
                        if (!tableColumMap.containsKey(k)) {
                           boolean needAddNewField = false;
                           if (BtmTypeFieldConstant.LINK_TYPE_FIELD_MAP.containsKey(attributeLowId)) {
                              //是链接类型的属性,以前没有就添加上
                              needAddNewField = true;
                           }
                           if (needAddNewField) {
                              addList.add(v.getId());
                           }
                        }
                     }
                  });
                  tableColumMap.forEach((k, v) -> {
                     if (!attributeMap.containsKey(k)) {
                        deleteList.add(k);
                     }
                  });
                  modifyAttributeInfo.setOrderModifyUserName(AuthUtil.getUserAccount());
                  modifyAttributeInfo.setOrderModifyDate(new Date());
                  modifyAttributeInfo.setModifyColumnReason(ModifyTableTaskEnum.CONSISTENCY_CHECK.getValue());
                  modifyAttributeInfo.setTaskName(ModifyTableTaskEnum.CONSISTENCY_CHECK.getValue());
                  modifyAttributeInfo.setAddAttributes(String.join(",", addList));
                  modifyAttributeInfo.setModifyAttributes(String.join(",", editList));
                  modifyAttributeInfo.setDeleteAttributes(String.join(",", deleteList));
                  modifyAttributeInfo.setBeforeModifyAttributes(String.join(",", beforeList));
               }
            }
      });
      return modifyAttributeInfoDOList;
   }
   /**
    * åˆ¤æ–­æ˜¯å¦éœ€è¦ä¿®æ”¹å±žæ€§
    *
    * @param btmTypeAttributeVO å±žæ€§çš„æ˜¾ç¤ºå¯¹è±¡
    * @param tableInDB          æ•°æ®åº“表里的对象
    * @return true表示需要修改,false表示不修改
    */
   private boolean checkNeedEditAttr(BtmTypeAttributeVO btmTypeAttributeVO, DdlTableInDataBaseBO tableInDB) {
      if (tableInDB.getAttributeLength() == null) {
         tableInDB.setAttributeLength(0);
      }
      if (tableInDB.getPrecisionLength() == null) {
         tableInDB.setPrecisionLength(20);
      }
      if (tableInDB.getScaleLength() == null) {
         tableInDB.setScaleLength(0);
      }
      String nullInDb = "";
      if (YES.equalsIgnoreCase(tableInDB.getNullableFlag())) {
         nullInDb = BooleanEnum.TRUE.getValue();
      } else if (NO.equalsIgnoreCase(tableInDB.getNullableFlag())) {
         nullInDb = BooleanEnum.FASLE.getValue();
      }
      if (!(String.valueOf(btmTypeAttributeVO.isNullableFlag()).equalsIgnoreCase(nullInDb))) {
         return true;
      }
      if (StringUtils.isNotBlank(btmTypeAttributeVO.getDefaultValue())) {
         return true;
      }
      List<VciFieldTypeEnum> fieldTypes = dllMapper.listFieldByColumnStr(tableInDB.getAttrDataType());
      if (CollectionUtils.isEmpty(fieldTypes)) {
         throw new VciBaseException("没有找到对应的字段类型");
      }
      Set<String> names = fieldTypes.stream().map(Enum::name).collect(Collectors.toSet());
      String attributeDataType = btmTypeAttributeVO.getAttrDataType();
      if (names.size() > 1) {
         return !names.contains(attributeDataType);
      } else {
         VciFieldTypeEnum fieldType = fieldTypes.get(0);
         if (attributeDataType.equalsIgnoreCase(fieldType.name())) {
            switch (fieldType) {
               case VTString:
                  if (btmTypeAttributeVO.getAttributeLength().intValue() != tableInDB.getAttributeLength().intValue()) {
                     return true;
                  }
                  break;
               case VTDouble:
                  //不超过128
                  if (btmTypeAttributeVO.getPrecisionLength().intValue() != tableInDB.getPrecisionLength().intValue()) {
                     return true;
                  }
                  if (btmTypeAttributeVO.getScaleLength().intValue() != tableInDB.getScaleLength().intValue()) {
                     return true;
                  }
                  break;
               default:
                  break;
            }
         }
         return false;
      }
   }
   /**
    * æ¸…理业务类型中和数据库里不一样的
    *
    * @param differentAttributeList ä¸åŒçš„属性的列表
    * @throws VciBaseException å‚数为空或者执行出错的时候会抛出异常
    */
   @Override
   public void reflexDifferent(List<ModifyAttributeInfo> differentAttributeList, List<BtmTypeVO> btmTypeVOList, List<LinkTypeVO> linkTypeVOList) throws VciBaseException {
      VciBaseUtil.alertNotNull(differentAttributeList, "要清理的数据库的信息为空");
      Map<String, BtmTypeVO> idBtmTypeMap = btmTypeVOList.stream().collect(Collectors.toMap(BtmTypeVO::getId, t -> t, (o1, o2) -> o1));
      Map<String, LinkTypeVO> idLinkTypeMap = linkTypeVOList.stream().collect(Collectors.toMap(LinkTypeVO::getId, t -> t, (o1, o2) -> o1));
      differentAttributeList.forEach(s -> {
//         BtmTypeVO btmType = idBtmTypeMap.get(id);
         if (ModifyTableTaskEnum.CREATE.getValue().equalsIgnoreCase(s.getTaskName())) {
            //直接创建表格
//            createDbTableForBtm(btmType);
            createDbTablesById(s.getId());
         } else {
            String addAttributes = s.getAddAttributes();
            if (StringUtils.isNotBlank(s.getModifyAttributes()) || StringUtils.isNotBlank(s.getDeleteAttributes())) {
               //需要去判断是否可以更改
               if (checkTableHasDataByTableName(s.getTableName())) {
                  //有数据的话,得需要判断属性是否可以修改
                  if (StringUtils.isNotBlank(s.getDeleteAttributes())) {
                     s.setHandleResult("表格存在数据,不允许删除字段");
                     return;
                  }
                  List<DdlTableInDataBaseBO> columnInDbList = selectTableColumnInfo(s.getTableName());
                  Map<String, DdlTableInDataBaseBO> columnInDbMap = new HashMap<>();
                  if (!CollectionUtils.isEmpty(columnInDbList)) {
                     columnInDbMap = columnInDbList.stream().collect(Collectors.toMap(t -> t.getId().toLowerCase(), k -> k));
                  }
                  List<BtmTypeAttributeVO> attributeVOList = idBtmTypeMap.getOrDefault(s.getId(), new BtmTypeVO()).getAttributes().stream().filter(vo -> Func.toStrList(",", s.getAddAttributes()).stream().anyMatch(id -> StringUtils.equals(vo.getId().toLowerCase(), id))).collect(Collectors.toList());
                  //有可能之前判断的时候数据库存在,而现在不存在了
                  List<String> unExitInDbIdList = new ArrayList<>();
                  Map<String, DdlTableInDataBaseBO> finalColumnInDbMap = columnInDbMap;
                  List<BtmTypeAttributeVO> needEditAttributeVOList = new ArrayList<>();
                  if (!CollectionUtils.isEmpty(attributeVOList)) {
                     attributeVOList.forEach(t -> {
                        if (finalColumnInDbMap.containsKey(t.getId().toLowerCase().trim())) {
                           needEditAttributeVOList.add(t);
                        } else {
                           unExitInDbIdList.add(t.getId());
                        }
                     });
                  }
                  if (!CollectionUtils.isEmpty(needEditAttributeVOList)) {
                     List<BtmTypeAttributeVO> unModifyAttrVOList = needEditAttributeVOList.stream().filter(t -> !checkNotCanEditAttr(t.getAttrDataType(), finalColumnInDbMap.get(t.getId().trim().toLowerCase()))).collect(Collectors.toList());
                     if (!CollectionUtils.isEmpty(unModifyAttrVOList)) {
                        s.setHandleResult("表格存在数据," + unModifyAttrVOList.stream().map(BtmTypeAttributeVO::getId).collect(Collectors.joining(",")) + "这些字段不能修改");
                        return;
                     }
                     needEditAttributeVOList.stream().forEach(t -> {
                        String attributeLowerId = t.getId().trim().toLowerCase();
                        DdlTableInDataBaseBO columInDb = finalColumnInDbMap.get(attributeLowerId);
                        if (!t.getName().equalsIgnoreCase(columInDb.getName())) {
                           ddlMapper.commentColumnTable(s.getTableName(), t.getId(), t.getName());
                        }
                        if (columInDb.getAttributeLength() != null && t.getAttributeLength() != null
                           && t.getAttributeLength() < columInDb.getAttributeLength()) {
                           t.setAttributeLength(columInDb.getAttributeLength());
                        }
                        List<BtmTypeAttributeVO> attributeVOS = new ArrayList<>();
                        boolean nowNeedNull = false;
                        if (!YES.equalsIgnoreCase(columInDb.getNullableFlag()) && !t.isNullableFlag()) {
                           //说明以前是不能为空的,但是以前也是不为空的,修改会报错,所以这个调整一下
                           t.setNullableFlag(true);
                        } else if (!YES.equalsIgnoreCase(columInDb.getNullableFlag()) && t.isNullableFlag()) {
                           //以前不为空,现在为空
                           nowNeedNull = true;
                        }
                        attributeVOS.add(t);
                        String attributeSql = getCreateSqlByAttributeForBtm(attributeVOS);
                        if (nowNeedNull) {
                           attributeSql += StringPool.SPACE + "null" + StringPool.SPACE;
                        }
                        ddlMapper.modifyTableBySql(s.getTableName(), attributeSql);
                     });
                  }
                  if (!CollectionUtils.isEmpty(unExitInDbIdList)) {
                     if (StringUtils.isBlank(addAttributes)) {
                        addAttributes = String.join(",", unExitInDbIdList);
                     } else {
                        addAttributes += "," + String.join(",", unExitInDbIdList);
                        ;
                     }
                  }
               } else {
                  //说明没有数据,那可以把修改的列和删除的列都删除,然后重新添加
                  if (StringUtils.isNotBlank(s.getModifyAttributes())) {
                     List<BtmTypeAttributeVO> attributeVOList = idBtmTypeMap.getOrDefault(s.getId(), new BtmTypeVO()).getAttributes().stream().filter(vo -> Func.toStrList(",", s.getModifyAttributes()).stream().anyMatch(id -> StringUtils.equals(vo.getId(), id))).collect(Collectors.toList());
                     if (!CollectionUtils.isEmpty(attributeVOList)) {
                        attributeVOList.forEach(t -> {
                           List<BtmTypeAttributeVO> attributeVOS = new ArrayList<>();
                           attributeVOS.add(t);
                           dropColumnByName(s.getTableName(), t.getId());
                           addColumnForTable(s.getTableName(), attributeVOS);
                           ddlMapper.commentColumnTable(s.getTableName(), t.getId(), t.getName());
                        });
                     }
                  }
                  //需要删除的列
                  if (StringUtils.isNotBlank(s.getDeleteAttributes())) {
                     List<String> attributeIdList = VciBaseUtil.str2List(s.getDeleteAttributes());
                     Optional.ofNullable(attributeIdList).orElseGet(ArrayList::new).forEach(t -> {
                        dropColumnByName(s.getTableName(), t);
                     });
                  }
               }
            }
            if (StringUtils.isNotBlank(addAttributes)) {
               //只是添加属性值
               if (BusinessTypeEnum.LINK.getValue().equalsIgnoreCase(s.getBusinessType())) {
                  List<LinkTypeAttributeVO> attributeVOList = idLinkTypeMap.getOrDefault(s.getId(), new LinkTypeVO()).getAttributes().stream().filter(vo -> Func.toStrList(",", s.getAddAttributes()).stream().anyMatch(id -> StringUtils.equals(vo.getId(), id))).collect(Collectors.toList());
                  //是链接类型
//                  List<LinkTypeAttributeVO> attributeVOList = linkTypeService.listAttributeVOByIdsForLink(s.getId(), VciBaseUtil.str2List(s.getAddAttributes()));
                  addColumn2TableForLink(attributeVOList);
               } else {
                  List<BtmTypeAttributeVO> attributeVOList = idBtmTypeMap.getOrDefault(s.getId(), new BtmTypeVO()).getAttributes().stream().filter(vo -> Func.toStrList(",", s.getAddAttributes()).stream().anyMatch(id -> StringUtils.equals(vo.getId(), id))).collect(Collectors.toList());
                  addColumn2TableForBtm(attributeVOList);
               }
            }
         }
      });
   }
   private boolean checkNotCanEditAttr(String attributeDataType, DdlTableInDataBaseBO tableInDB) {
      if (tableInDB != null && StringUtils.isNotBlank(attributeDataType)) {
         List<VciFieldTypeEnum> fieldTypeEnums = dllMapper.listFieldByColumnStr(tableInDB.getAttrDataType());
         Set<String> names = fieldTypeEnums.stream().map(Enum::name).collect(Collectors.toSet());
         if (names.contains(attributeDataType)) {
            return true;
         }
         return true;
      } else {
         //因为数据库里没有这个表格时
         return true;
      }
   }
   /**
    * èŽ·å–æ•°æ®åº“ä¸­æ‰€æœ‰çš„è¡¨æ ¼
    *
    * @return è¡¨æ ¼çš„名称,全是大写
    */
   @Override
   public List<String> listAllTableName() {
      return ddlMapper.selectAllTableName();
   }
   /**
    * æŸ¥è¯¢æ•°æ®åº“中的表格信息
    *
    * @param tableNamesCollections æ•°æ®åº“表名集合
    * @return åœ¨æ•°æ®åº“中的信息
    * @throws VciBaseException å‚数为空或者数据库表不存在的时候会抛出异常
    */
   @Override
   public List<DdlTableBO> listTableInfoInDB(Collection<String> tableNamesCollections) throws VciBaseException {
      VciBaseUtil.alertNotNull("数据库表名称不能为空", tableNamesCollections);
      List<DdlTableBO> 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<String> 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<String> 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 ddlDTO ä¸šåŠ¡ç±»åž‹é“¾æŽ¥ç±»åž‹ä¼ è¾“å¯¹è±¡
    * @return æ‰§è¡Œç»“æžœ
    */
   @Override
   public R<List<ModifyAttributeInfo>> submit(BtmAndLinkTypeDdlDTO ddlDTO) {
      try {
         List<ModifyAttributeInfo> changedList = new ArrayList<>();
         if (!CollectionUtils.isEmpty(ddlDTO.getBtmTypeList())) {
            List<BtmTypeVO> btmTypeList = ddlDTO.getBtmTypeList();
            putBtm(btmTypeList.toArray(new BtmTypeVO[0]));
            changedList.addAll(checkDifferent(btmTypeList, null));
            removeBtm(btmTypeList.toArray(new BtmTypeVO[0]));
         }
         if (!CollectionUtils.isEmpty(ddlDTO.getLinkTypeList())) {
            List<LinkTypeVO> linkTypeList = ddlDTO.getLinkTypeList();
            putLink(linkTypeList.toArray(new LinkTypeVO[0]));
            changedList.addAll(checkDifferent(null,linkTypeList));
            removeLink(linkTypeList.toArray(new LinkTypeVO[0]));
         }
         R<List<ModifyAttributeInfo>> result = R.success("数据库操作成功");
         result.setData(changedList);
         return result;
      } catch (ServiceException e) {
         throw new RuntimeException(e.getMessage());
      }
   }
   /**
    * æŒ‰è¡¨åèŽ·å–è¡¨ä¿¡æ¯
    *
    * @param tableName è¡¨å
    * @return è¡¨ä¿¡æ¯
    */
   @Override
   public DdlTableBO getTableColumnByTableName(String tableName) {
      VciBaseUtil.alertNotNull(tableName, "表名");
      DdlTableBO tableBO = getTableInfoByTableName(tableName);
      List<DdlTableInDataBaseBO> columnInfo = selectTableColumnInfo(tableName);
      tableBO.setColumns(columnInfo);
      return tableBO;
   }
   /**
    * æŸ¥è¯¢æ•°æ®åº“中表格的字段信息
    *
    * @param tableName è¡¨æ ¼çš„名称
    * @return æ•°æ®åº“表的字段信息
    */
   private List<DdlTableInDataBaseBO> 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<BtmTypeVO> getAllTableInfo() {
      List<String> allTableName = listAllTableName();
      if (!CollectionUtils.isEmpty(allTableName)) {
         List<DdlTableBO> allTableBO = listTableInfoInDB(allTableName);
         List<BtmTypeVO> btmTypeVOList = new ArrayList<>();
         allTableBO.forEach(table -> {
            BtmTypeVO vo = new BtmTypeVO();
            vo.setTableName(table.getTableName());
            vo.setDescription(table.getTableDesc());
            List<DdlTableInDataBaseBO> columns = selectTableColumnInfo(table.getTableName());
            List<BtmTypeAttributeVO> attributes = new ArrayList<>();
            columns.forEach(col -> {
               BtmTypeAttributeVO attributeVO = new BtmTypeAttributeVO();
               attributeVO.setId(col.getId());
               attributeVO.setName(col.getName());
               attributeVO.setNullableFlag(col.getNullableFlag());
               attributeVO.setAttributeLength(col.getAttributeLength());
               attributeVO.setPrecisionLength(col.getPrecisionLength());
               attributeVO.setScaleLength(col.getScaleLength());
               VciFieldTypeEnum field = dllMapper.getFieldTypeByColumnStr(col.getAttrDataType(), col.getAttributeLength());
               if (field != null){
                  attributeVO.setAttrDataType(field.name());
               }
               attributes.add(attributeVO);
            });
            vo.setAttributes(attributes);
            btmTypeVOList.add(vo);
         });
         return btmTypeVOList;
      }
      return new ArrayList<>();
   }
}