I'm currently migrating from PostgreSQL to Oracle DBMS. but occur some problem. I wish to work "Insert all with sequence and return sequence to application using usegeneratekeys in mybatis."
My PostgreSQL Code is (it also works MySQL and 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>
I tried to cases. see the below.
CASE 1
It does work in Oracle, But It does not work in mybatis, does not return sequence.
1.create sequnece
Create Sequence service_code_seq;
2.create function for 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 code for insert all
<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>
CASE 2
It does work in Oracle, But It does not work in mybatis, does not return sequence.
<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>
I wish to migrate from PostgreSQL to Oracle without modifying application code, migrate only SQL Code.
Thanks!!
It seems that returning generated keys from 'multi-row insert' is not supported by Oracle's driver.
So, it may not be possible "without modifying application code".
FYI, it may work if you switch to 'batch insert'.
It also performs better when inserting a lot of rows.
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();
}
The mapper statement is straightforward.
<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>