mybatis是否允许在oracle中插入所有和return序列(useGenerateKeys)?

Is mybatis enable to insert all and return sequence(useGenerateKeys) in oracle?

我目前正在从 PostgreSQL 迁移到 Oracle DBMS。但出现一些问题。我想工作 "Insert all with sequence and return sequence to application using in mybatis."

我的 PostgreSQL 代码是(它也适用于 MySQL 和 MariaDB)

 <insert id="insertServiceCodeList" parameterType="serviceCodeVo" useGeneratedKeys="true" keyColumn="code" keyProperty="code">
    insert into service_code (
        serv_info_seq_id,
        name,
        default_key_type,
        cre_date,
        creator,
        description,
        state
    ) values 
    <foreach collection="list" item="item" separator=","> 
    (
        #{item.servInfoSeqId},
        #{item.name},
        #{item.defaultKeyType},
        now(),
        #{item.creator},
        #{item.description},
        0
    )
    </foreach>
</insert>

我试过例。见下文。

案例 1

在Oracle中可以,但在mybatis中不能,不return序列。

1.create 序列

Create Sequence service_code_seq;

2.create sequence.nextval

函数
create or replace function get_seq( seq_name in varchar2 ) 
return 
  number 
is
  v_num number;
  sql_stmt varchar2(64);
begin
  sql_stmt := 'select ' || seq_name || '.nextval from dual';
  execute immediate sql_stmt into v_num;
  return v_num;
end;

3.mybatis 全部插入的代码

<insert id="insertServiceCodeList" parameterType="serviceCodeVo" useGeneratedKeys="true" keyColumn="code" keyProperty="code">
insert all
     <foreach collection="list" item="item" >
        into service_code (
            code,
            serv_info_seq_id,
            name,
            default_key_type,
            cre_date,
            creator,
            description,
            state
        ) values (
            get_seq( 'service_code_seq' ),
            #{item.servInfoSeqId},
            #{item.name},
            #{item.defaultKeyType},
            systimestamp,
            #{item.creator},
            #{item.description},
            0
        )
    </foreach>
    select * from dual;
</insert>

案例 2

在Oracle中可以,但在mybatis中不能,不return序列。

<insert id="insertServiceCodeList" parameterType="serviceCodeVo" useGeneratedKeys="true" keyColumn="code" keyProperty="code">
    insert into service_code (
        code,
        serv_info_seq_id,
        name,
        default_key_type,
        cre_date,
        creator,
        description,
        state
    ) select
        service_code_seq.nextval,
        servInfoSeqId,
        name,
        defaultKeyType,
        systimestamp,
        creator,
        description,
        0
    from (
    <foreach collection="list" item="item" separator="union all"> 
        select
            #{item.servInfoSeqId} servInfoSeqId,
            #{item.name} name,
            #{item.defaultKeyType} defaultKeyType,
            #{item.creator} creator,
            #{item.description} description
        from
            dual
    </foreach>
    )
</insert>

我希望在不修改应用程序代码的情况下从 PostgreSQL 迁移到 Oracle,仅迁移 SQL 代码。

谢谢!!

Oracle 的驱动程序似乎不支持从 'multi-row insert' 返回生成的密钥。
所以,这可能是不可能的 "without modifying application code".

仅供参考,如果您切换到 'batch insert',它可能会起作用。
它在插入大量行时也表现更好。

int batchSize = 1000;
try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
  YourMapper mapper = sqlSession.getMapper(YourMapper.class);
  int size = serviceCodeList.size();
  for (int i = 0; i < size;) {
    mapper.insertServiceCode(serviceCodeList.get(i));
    i++;
    if (i % batchSize == 0 || i == size) {
      sqlSession.flushStatements();
      sqlSession.clearCache();
    }
  }
  sqlSession.commit();
}

映射器语句很简单。

<insert id="insertServiceCode" useGeneratedKeys="true"
    keyColumn="code" keyProperty="code">
  insert into service_code (
    code,
    serv_info_seq_id,
    name,
    default_key_type,
    cre_date,
    creator,
    description,
    state
  ) values (
    service_code_seq.nextval,
    #{item.servInfoSeqId},
    #{item.name},
    #{item.defaultKeyType},
    systimestamp,
    #{item.creator},
    #{item.description},
    0
  )
</insert>