集团项目信创改造3 mysql to dm 插入获取主键

又是我,集团项目新创改造,这次其实是一个我之前处理过的,一个其实蛮简单的问题,插入获取主键

其实之前的写法大概是

之前版本

sql 复制代码
 <!-- 新建闲置单,将单据编号、状态插入数据库中 -->
    <insert id="insertAssetIdleHeaderInFo" parameterType="cn.chinaunicom.ams.assetIdle.entity.AssetIdle">
        insert into  cams_idle_header_all
        <trim prefix="(" suffix=")" suffixOverrides=",">

            <if test="bookTypeCode != null">
                BOOK_TYPE_CODE,
            </if>
            <if test="billNumber != null">
                IDLE_NUMBER,
            </if>
            <if test="billTitle != null and  billTitle != '' ">
                IDLE_TITLE,
            </if>
            <if test="areaCode != null"  >
                IDLE_DEPT_CODE,
            </if>
            <if test="areaName != null">
                IDLE_DEPT_NAME,
            </if>
            <if test="status != null">
                STATUS,
            </if>
            LAST_UPDATE_DATE,
            <if test="staffId != null">
                DOC_EMPLOYEE_NUMBER,
                LAST_UPDATED_BY,
                CREATED_BY,
            </if>
            <if test="staffName != null">
                DOC_EMPLOYEE_NAME,
            </if>
            CREATION_DATE,

            <if test="bgId != null">
                BG_ID,
            </if>
            <if test="ouId != null">
                ORG_ID,
            </if>
            <if test="dpId != null and  dpId != ''">
                DEPT_ID,
            </if>
            <if test="createdDuty != null">
                created_Duty,
            </if>
            <if test="ouName != null">
                ou_name,
            </if>
            <if test="createRoleId != null">
                CREATE_ROLE_ID,
            </if>
            <if test="staffErpCode != null and  staffErpCode != ''">
                STAFF_ERP_CODE,
            </if>
            <if test="idleDate != null and  idleDate != ''">
                IDLE_DATE,
            </if>
            <if test="idleNote != null and  idleNote != ''">
                IDLE_NOTE,
            </if>
            <if test="completedBy != null and  completedBy != ''">
                COMPLETED_BY,
            </if>
            <if test="completeDate != null and  completeDate != ''">
                COMPLETE_DATE,
            </if>
            <if test="periodName != null and  periodName != ''">
                PERIOD_NAME,
            </if>
            <if test="approvedBy != null and  approvedBy != ''">
                APPROVED_BY,
            </if>
            <if test="approvedDate != null and  approvedDate != ''">
                APPROVED_DATE,
            </if>
            <if test="specialType != null and  specialType != ''">
                SPECIAL_TYPE,
            </if>
            <if test="specialId != null and  specialId != ''">
                SPECIAL_ID,
            </if>
            <if test="specialSubclass != null and  specialSubclass != ''">
                SPECIAL_SUBCLASS,
            </if>
            <if test="specialSubclassId != null and  specialSubclassId != ''">
                SPECIAL_SUBCLASS_ID,
            </if>
            <if test="assetStatus != null and  assetStatus != ''">
                ASSET_STATUS,
            </if>
            <if test="assetSubStatus != null and  assetSubStatus != ''">
                ASSET_SUB_STATUS,
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="bookTypeCode != null">
                #{bookTypeCode,jdbcType=VARCHAR},
            </if>
            <if test="billNumber != null">
                #{billNumber,jdbcType=VARCHAR},
            </if>
            <if test="billTitle != null and  billTitle != '' ">
                #{billTitle,jdbcType=VARCHAR},
            </if>
            <if test="areaCode != null">
                #{areaCode,jdbcType=VARCHAR},
            </if>
            <if test="areaName != null">
                #{areaName,jdbcType=VARCHAR},
            </if>
            <if test="status != null">
                #{status,jdbcType=VARCHAR},
            </if>
            current_timestamp(),
            <if test="staffId != null">
                #{staffId,jdbcType=BIGINT},
                #{staffId,jdbcType=BIGINT},
                #{staffId,jdbcType=BIGINT},
            </if>
            <if test="staffName != null">
                #{staffName,jdbcType=VARCHAR},
            </if>
            current_timestamp(),
            <if test="bgId != null">
                #{bgId},
            </if>

            <if test="ouId != null">
                #{ouId},
            </if>
            <if test="dpId != null and  dpId != ''">
                #{dpId},
            </if>
            <if test="createdDuty != null">
                #{createdDuty},
            </if>
            <if test="ouName != null">
                #{ouName},
            </if>
            <if test="createRoleId != null">
                #{createRoleId},
            </if>
            <if test="staffErpCode != null and  staffErpCode != ''">
                #{staffErpCode},
            </if>
            <if test="idleDate != null and  idleDate != ''">
                #{idleDate},
            </if>
            <if test="idleNote != null and  idleNote != ''">
                #{idleNote},
            </if>
            <if test="completedBy != null and  completedBy != ''">
                #{completedBy},
            </if>
            <if test="completeDate != null and  completeDate != ''">
                #{completeDate},
            </if>
            <if test="periodName != null and  periodName != ''">
                #{periodName},
            </if>
            <if test="approvedBy != null and  approvedBy != ''">
                #{approvedBy},
            </if>
            <if test="approvedDate != null and  approvedDate != ''">
                #{approvedDate},
            </if>
            <if test="specialType != null and  specialType != ''">
                #{specialType},
            </if>
            <if test="specialId != null and  specialId != ''">
                #{specialId},
            </if>
            <if test="specialSubclass != null and  specialSubclass != ''">
                #{specialSubclass},
            </if>
            <if test="specialSubclassId != null and  specialSubclassId != ''">
                #{specialSubclassId},
            </if>
            <if test="assetStatus != null and  assetStatus != ''">
                #{assetStatus},
            </if>
            <if test="assetSubStatus != null and  assetSubStatus != ''">
                #{assetSubStatus},
            </if>
        </trim>

        <selectKey resultType="java.lang.Long" keyProperty="headerId" order="AFTER">
            SELECT LAST_INSERT_ID()
        </selectKey>

    </insert>

这是之前的mysql 的写法,

sql 复制代码
  <!-- 新建闲置单,将单据编号、状态插入数据库中 -->
    <insert id="insertAssetIdleHeaderInFo" parameterType="cn.chinaunicom.ams.assetIdle.entity.AssetIdle"
            useGeneratedKeys="true" keyProperty="headerId">insert into  cams_idle_header_all
        <trim prefix="(" suffix=")" suffixOverrides=",">

            <if test="bookTypeCode != null">
                BOOK_TYPE_CODE,
            </if>
            <if test="billNumber != null">
                IDLE_NUMBER,
            </if>
            <if test="billTitle != null and  billTitle != '' ">
                IDLE_TITLE,
            </if>
            <if test="areaCode != null"  >
                IDLE_DEPT_CODE,
            </if>
            <if test="areaName != null">
                IDLE_DEPT_NAME,
            </if>
            <if test="status != null">
                STATUS,
            </if>
            LAST_UPDATE_DATE,
            <if test="staffId != null">
                DOC_EMPLOYEE_NUMBER,
                LAST_UPDATED_BY,
                CREATED_BY,
            </if>
            <if test="staffName != null">
                DOC_EMPLOYEE_NAME,
            </if>
            CREATION_DATE,

            <if test="bgId != null">
                BG_ID,
            </if>
            <if test="ouId != null">
                ORG_ID,
            </if>
            <if test="dpId != null and  dpId != ''">
                DEPT_ID,
            </if>
            <if test="createdDuty != null">
                created_Duty,
            </if>
            <if test="ouName != null">
                ou_name,
            </if>
            <if test="createRoleId != null">
                CREATE_ROLE_ID,
            </if>
            <if test="staffErpCode != null and  staffErpCode != ''">
                STAFF_ERP_CODE,
            </if>
            <if test="idleDate != null and  idleDate != ''">
                IDLE_DATE,
            </if>
            <if test="idleNote != null and  idleNote != ''">
                IDLE_NOTE,
            </if>
            <if test="completedBy != null and  completedBy != ''">
                COMPLETED_BY,
            </if>
            <if test="completeDate != null and  completeDate != ''">
                COMPLETE_DATE,
            </if>
            <if test="periodName != null and  periodName != ''">
                PERIOD_NAME,
            </if>
            <if test="approvedBy != null and  approvedBy != ''">
                APPROVED_BY,
            </if>
            <if test="approvedDate != null and  approvedDate != ''">
                APPROVED_DATE,
            </if>
            <if test="specialType != null and  specialType != ''">
                SPECIAL_TYPE,
            </if>
            <if test="specialId != null and  specialId != ''">
                SPECIAL_ID,
            </if>
            <if test="specialSubclass != null and  specialSubclass != ''">
                SPECIAL_SUBCLASS,
            </if>
            <if test="specialSubclassId != null and  specialSubclassId != ''">
                SPECIAL_SUBCLASS_ID,
            </if>
            <if test="assetStatus != null and  assetStatus != ''">
                ASSET_STATUS,
            </if>
            <if test="assetSubStatus != null and  assetSubStatus != ''">
                ASSET_SUB_STATUS,
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="bookTypeCode != null">
                #{bookTypeCode,jdbcType=VARCHAR},
            </if>
            <if test="billNumber != null">
                #{billNumber,jdbcType=VARCHAR},
            </if>
            <if test="billTitle != null and  billTitle != '' ">
                #{billTitle,jdbcType=VARCHAR},
            </if>
            <if test="areaCode != null">
                #{areaCode,jdbcType=VARCHAR},
            </if>
            <if test="areaName != null">
                #{areaName,jdbcType=VARCHAR},
            </if>
            <if test="status != null">
                #{status,jdbcType=VARCHAR},
            </if>
            current_timestamp(),
            <if test="staffId != null">
                #{staffId,jdbcType=BIGINT},
                #{staffId,jdbcType=BIGINT},
                #{staffId,jdbcType=BIGINT},
            </if>
            <if test="staffName != null">
                #{staffName,jdbcType=VARCHAR},
            </if>
            current_timestamp(),
            <if test="bgId != null">
                #{bgId},
            </if>

            <if test="ouId != null">
                #{ouId},
            </if>
            <if test="dpId != null and  dpId != ''">
                #{dpId},
            </if>
            <if test="createdDuty != null">
                #{createdDuty},
            </if>
            <if test="ouName != null">
                #{ouName},
            </if>
            <if test="createRoleId != null">
                #{createRoleId},
            </if>
            <if test="staffErpCode != null and  staffErpCode != ''">
                #{staffErpCode},
            </if>
            <if test="idleDate != null and  idleDate != ''">
                #{idleDate},
            </if>
            <if test="idleNote != null and  idleNote != ''">
                #{idleNote},
            </if>
            <if test="completedBy != null and  completedBy != ''">
                #{completedBy},
            </if>
            <if test="completeDate != null and  completeDate != ''">
                #{completeDate},
            </if>
            <if test="periodName != null and  periodName != ''">
                #{periodName},
            </if>
            <if test="approvedBy != null and  approvedBy != ''">
                #{approvedBy},
            </if>
            <if test="approvedDate != null and  approvedDate != ''">
                #{approvedDate},
            </if>
            <if test="specialType != null and  specialType != ''">
                #{specialType},
            </if>
            <if test="specialId != null and  specialId != ''">
                #{specialId},
            </if>
            <if test="specialSubclass != null and  specialSubclass != ''">
                #{specialSubclass},
            </if>
            <if test="specialSubclassId != null and  specialSubclassId != ''">
                #{specialSubclassId},
            </if>
            <if test="assetStatus != null and  assetStatus != ''">
                #{assetStatus},
            </if>
            <if test="assetSubStatus != null and  assetSubStatus != ''">
                #{assetSubStatus},
            </if>
        </trim>

    </insert>

这个是达梦数据库的写法,其实就是一个简单的问题,

<selectKey resultType="java.lang.Long" keyProperty="headerId" order="AFTER"> SELECT LAST_INSERT_ID() </selectKey>修改成useGeneratedKeys="true" keyProperty="headerId"的写法,其实这个不好使,LAST_INSERT_ID()是因为这个函数不好使,而不是selectKey 不好使,之前我也是不知道,为什么我知道了呢,是因为下面这个问题。

java 复制代码
  /**
     * 复制流程
     * ict使用-流程配置
     *
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addFlow(FlowCfgType type) throws Exception {
        // 判断是复制还是升级(1:升级;0:复制)
        Short isUpgrade = type.getIsUpgrade();
        if (isUpgrade == null || (isUpgrade != 1 && isUpgrade != 0)) {
            throw new RuntimeException("升级和复制功能不明确,请重新操作");
        }
        //type表复制
        int a = flowCfgTypeMapper.addCopyType(type);
        String flowTypeId = null;
        if (a > 0) {
            flowTypeId = flowCfgTypeMapper.selectLastId();
        }
        type.setFlowTypeId(flowTypeId);
        //获取当前用户ip
        // String ip = IPCheck.getIpAddr(request);
        InetAddress localhost = NetUtil.getLocalhost();
        String ip = localhost.getHostAddress();
        //插入一条历史复制记录
        flowCfgLogMapper.addCopyTypeOperHst(type.getFlowTypeId(), WebUtil.getNowUser().getLoginName(), "c", ip, type.getOriginalTypeId());
        //查询原始的节点的id
        List<FlowCfgLink> originalList = flowCfgLinkMapper.selectOriginalFlow(type.getOriginalTypeId());
        if (originalList == null || originalList.isEmpty()) {
            throw new Exception("linkError");
        }
        flowCfgLinkMapper.addCopylink(type);//link表复制
        //flowCfgLinkMapper.addCopylinkXy(type);//linkXy表复制  该表已不使用
        //查询复制后的节点的id
        List<FlowCfgLink> newList = flowCfgLinkMapper.selectNewFlow(type.getFlowTypeId());

        Map<String, String> linkMap = new HashMap<>();
        List<String> linkIds = new ArrayList<String>();
        for (FlowCfgLink oLink : originalList) {
            for (FlowCfgLink nLink : newList) {
                if (oLink.getLinkKey().equals(nLink.getLinkKey())) {
                    linkMap.put(oLink.getFlowLinkId(), nLink.getFlowLinkId());
                }
            }
            linkIds.add(oLink.getFlowLinkId());
        }
        List<FlowCfgPath> pathList = flowCfgPathMapper.selectPath4LinkId(linkIds);
        if (pathList == null || pathList.isEmpty()) {
            throw new Exception("pathError");
        }
        for (FlowCfgPath flowCfgPath : pathList) {
            flowCfgPath.setFlowLinkId(linkMap.get(flowCfgPath.getFlowLinkId()));
            if (!flowCfgPath.getToFlowLinkId().contains("endevent")) {
                flowCfgPath.setToFlowLinkId(linkMap.get(flowCfgPath.getToFlowLinkId()));
            }
            //路径表复制
            flowCfgPathMapper.addCopyPath(flowCfgPath);
        }

        // 由于参与方式涉及到组织等,复制后注意参与者,需手动修改不符合组织的参与者
        List<FlowCfgJoin> joinList = flowCfgLinkMapper.selectJoin4LinkId(linkIds);
        if (joinList != null && !joinList.isEmpty()) {
            for (FlowCfgJoin flowCfgJoin : joinList) {
                flowCfgJoin.setFlowLinkId(linkMap.get(flowCfgJoin.getFlowLinkId()));
            }
            //参与属性表复制
            flowCfgLinkMapper.addCopyJoin(joinList);

            if (isUpgrade == 1) {
                List<FlowCfgJoin> idList = flowCfgLinkMapper.selectJoinId(type);
                // 如果为升级,则复制join_ext表
                List<FlowCfgJoinExt> joinExtList = flowCfgLinkMapper.selectJoinExt4JoinIds(idList);
                if (joinExtList != null && !joinExtList.isEmpty()) {
                    List<FlowCfgJoin> newJoinList = flowCfgLinkMapper.selectJoinList(idList);
                    if (newJoinList != null && !newJoinList.isEmpty()) {
                        for (FlowCfgJoinExt joinExt : joinExtList) {
                            for (FlowCfgJoin flowCfgJoin : joinList) {
                                if (joinExt.getJoinId().equals(flowCfgJoin.getFlowJoinId())) {
                                    for (FlowCfgJoin newJoin : newJoinList) {
                                        if (flowCfgJoin.getFlowLinkId().equals(newJoin.getFlowLinkId())) {
                                            joinExt.setJoinId(newJoin.getFlowJoinId());
                                        }
                                    }
                                }
                            }
                        }
                        //参与属性扩展表复制
                        flowCfgLinkMapper.addCopyJoinExt(joinExtList);
                    }
                }
            }
        }
        return type.getFlowTypeId();
    }

这个功能大概就是在一个复制一个工作流,其实蛮尴尬的,就是//type表复制 int a = flowCfgTypeMapper.addCopyType(type); String flowTypeId = null; if (a > 0) { flowTypeId = flowCfgTypeMapper.selectLastId(); }

我觉得还是蛮炸裂的,确实是一个是创建一条记录,一个是创建记录了之后,去获取最新的记录,但是吧,因为上面的写法,我觉得可以在插入的时候直接拿到对应的值把,不过该说不说这个写法是真的蠢啊,真的不考虑高并发的么,然后我想变成一个mapper直接去处理,

java 复制代码
  <insert id="addCopyType" parameterType="cn.chinaunicom.workflow.center.expand.entity.FlowCfgType">
    insert into FLOW_CFG_TYPE
		(flow_type_id,FLOW_KEY,FLOW_KEY_REV,FLOW_NAME,URL,HIST_URL,
		STATUS,STARTTIME,BG_ID,ORG_ID)
	select (select flow_type_id from flow_cfg_type order by flow_type_id desc FETCH FIRST 1 ROWS ONLY)+1,t.FLOW_KEY,
	    #{flowKeyRev,jdbcType=VARCHAR},#{flowName,jdbcType=VARCHAR},t.URL,t.HIST_URL, 0,SYSDATE,
		<if test="bgId!=0">
		#{bgId,jdbcType=INTEGER},
		</if>
		<if test="bgId==0">
		t.BG_ID,
		</if>#{orgId,jdbcType=INTEGER} from FLOW_CFG_TYPE t WHERE
		t.FLOW_TYPE_ID = #{originalTypeId,jdbcType=VARCHAR}
  </insert>

这是他原本的写法

然后我想转换成可以直接获取id的写法,并且因为id是主键而且是自增的,主键也不需要去进行插入,可以将这操作直接交给数据库,

sql 复制代码
  <insert id="addCopyType" parameterType="cn.chinaunicom.workflow.center.expand.entity.FlowCfgType"
          useGeneratedKeys="true" keyProperty="flowTypeId">
    insert into FLOW_CFG_TYPE
		(FLOW_KEY,
		 FLOW_KEY_REV,
		 FLOW_NAME,
		 URL,
		 HIST_URL,
		STATUS,
		 STARTTIME,
		 BG_ID,
		 ORG_ID)
	select t.FLOW_KEY,
	    #{flowKeyRev,jdbcType=VARCHAR},
	        #{flowName,jdbcType=VARCHAR},
	        t.URL,
	        t.HIST_URL,
	        0,
	        SYSDATE,
		<if test="bgId!=0">
		#{bgId,jdbcType=INTEGER},
		</if>
		<if test="bgId==0">
		t.BG_ID,
		</if>#{orgId,jdbcType=INTEGER}
		from FLOW_CFG_TYPE t WHERE
		t.FLOW_TYPE_ID = #{originalTypeId,jdbcType=VARCHAR}
  </insert>

理论上来说这样是可信的,但是我确实看到了flowTypeId值是0,贼尴尬,我不知道为啥,然后我去问了问ai。

ai 复制代码
为什么 flowTypeId 返回 0?
useGeneratedKeys="true" 只对数字类型的主键有效,具体限制如下:

✅ 支持: NUMBER、INTEGER、BIGINT 等数字类型(配合数据库自增或序列)
❌ 不支持: VARCHAR、CHAR 等字符类型
对于 insert into ... select ... 语法:

MyBatis 无法通过 useGeneratedKeys 获取生成的主键
因为这不是简单的单行插入,而是从查询结果插入

useGeneratedKeys="true" 在您的场景下无法正常工作,原因有三:

字段类型不匹配: FLOW_TYPE_ID 是 VARCHAR 类型,而 useGeneratedKeys 主要支持数字类型主键
SQL语法限制: insert into ... select ... 语法不支持返回生成的主键
缺少主键生成机制: 您的SQL没有显式指定 FLOW_TYPE_ID 的值

然后 我改了,挺麻烦的,给String类型修改成int

但是问题又来了,还是显示不大对,还是显示0,

然后我不是很理解 我又去问了问ai,结果就是

ai 复制代码
🎯 达梦数据库的特殊性
达梦数据库虽然兼容 Oracle 和 MySQL,但在以下场景中 useGeneratedKeys 无法正常工作:

❌ insert into ... select ... 语法 - 您当前的情况
❌ 批量插入
⚠️ 某些复杂插入场景

达梦的 useGeneratedKeys 支持情况

SQL 类型 useGeneratedKeys 支持 说明
INSERT INTO ... VALUES(...) ✅ 支持 简单插入
INSERT INTO ... SELECT ... ❌ 不支持 子查询插入
批量插入 ⚠️ 部分支持 需要特殊配置
实话说我是没想到,SELECT 不支持!!!!
然后通过ai修改了代码
sql 复制代码
 <insert id="addCopyType" parameterType="cn.chinaunicom.workflow.center.expand.entity.FlowCfgType"
          useGeneratedKeys="true" keyProperty="flowTypeId">
      <selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="flowTypeId">
          SELECT MAX(FLOW_TYPE_ID) FROM FLOW_CFG_TYPE
      </selectKey>
    insert into FLOW_CFG_TYPE
		(FLOW_KEY,
		 FLOW_KEY_REV,
		 FLOW_NAME,
		 URL,
		 HIST_URL,
		STATUS,
		 STARTTIME,
		 BG_ID,
		 ORG_ID)
	select t.FLOW_KEY,
	    #{flowKeyRev,jdbcType=VARCHAR},
	        #{flowName,jdbcType=VARCHAR},
	        t.URL,
	        t.HIST_URL,
	        0,
	        SYSDATE,
		<if test="bgId!=0">
		#{bgId,jdbcType=INTEGER},
		</if>
		<if test="bgId==0">
		t.BG_ID,
		</if>#{orgId,jdbcType=INTEGER}
		from FLOW_CFG_TYPE t WHERE
		t.FLOW_TYPE_ID = #{originalTypeId,jdbcType=VARCHAR}
  </insert>

然后就是完整的写法

相关推荐
zengjuan10051 小时前
[特殊字符]️ 松鼠备份 | 数据库备份方案即将重磅上线!三大模式组合拳,精准守护SQL Server每一笔数据
数据库·sqlserver·数据库备份·全量备份·增量备份·差异备份·日志和事务备份
auspicious航1 小时前
PostgreSQL统计信息:SQL调优的“眼睛”与基石
数据库·sql·postgresql
oradh2 小时前
Oracle RMAN备份元数据管理
数据库·oracle·rman备份元数据管理·rman catalog
程序猿乐锅2 小时前
从 dsh 源码看「一切皆插件」与 Spring IoC
java·网络·数据库·人工智能·后端·spring
这就是佬们吗2 小时前
AI Agent 的四根支柱:LLM、工具、记忆与规划是如何协同的
大数据·数据库·人工智能
lq_bog2 小时前
spring事务失效
java·数据库·spring
人机(未转人工)2 小时前
Flask + MySQL + Ollama(DeepSeek) 漏洞资产库 的网络安全资产分析平台的templates中(chat.html)渲染文件
mysql·flask·html