mybatis batch insert generating duplicate uuid primary key - insert

when i insert single record:
<insert id="add" parameterType="SysUser">
<selectKey keyProperty="id" resultType="String" order="BEFORE">
select replace(uuid(),'-','') from dual
</selectKey>
insert into sys_user(id,user_name,user_email,user_info,user_password,create_time)
values
(#{id,jdbcType=VARCHAR},
#{userName,jdbcType=VARCHAR},
#{userEmail,jdbcType=VARCHAR},
#{userInfo,jdbcType=VARCHAR},
#{userPassword,jdbcType=VARCHAR},
#{createTime,jdbcType=TIMESTAMP})
</insert>
but i want to insert a list, how can i generate the uuid like the single insert above???
<insert id="addSysUsers" parameterType="List" useGeneratedKeys="true" keyProperty="id">
INSERT INTO sys_user(user_name,user_password,user_email)
VALUES
<foreach collection="sysUsers" item="sysUser" separator=",">
(#{sysUser.userName,jdbcType=VARCHAR},#{sysUser.userPassword,jdbcType=VARCHAR},#{sysUser.userEmail,jdbcType=VARCHAR})
</foreach>
</insert>

The simplest way to do it is put the UUID generator in the values block:
<insert id="add" parameterType="SysUser">
insert into sys_user(id,user_name,user_email,user_info,user_password,create_time)
values
(replace(uuid(),'-',''), <!-- create uuid directly here --->
#{userName,jdbcType=VARCHAR},
#{userEmail,jdbcType=VARCHAR},
#{userInfo,jdbcType=VARCHAR},
#{userPassword,jdbcType=VARCHAR},
#{createTime,jdbcType=TIMESTAMP})
</insert>

Related

how do you use a liquibase parameter in an insert statement?

There is a liquibase parameter in Spring boot, let's say:
spring.liquibase.parameters.val1 = value1
I want to use this parameter in a sql file like this:
insert into table1 (name, value) values ("nameOfValue", ${val1});
unfortunately, the only combination that so far worked was putting 3 single quotes - '''${val1}''' (which gives 'value1') and substring removing the first and last single quote.
Is there a more clean way of using liquibase parameters in an INSERT statement in SQL changeset files?
It looks like you don't have to do anything special to insert a parameter from the properties no matter the chosen format of the changeset.
All of the following will result in valid insert statements.
SQL changeset
--changeset me:2
insert into test1 (id, name) values (1, 'name 1');
insert into test1 (id, name) values (3, '${val1}');
YAML changeset
- changeSet:
id: 2
author: me
changes:
- sql:
endDelimiter: ;
sql: >-
insert into test1 (id, name) values (1, 'name 1');
insert into test1 (id, name) values (3, '${val1}');
XML changeset:
<changeSet id="2" author="me">
<sql endDelimiter=";">
insert into test1 (id, name) values (1, 'name 1');
insert into test1 (id, name) values (3, '${val1}');
</sql>
</changeSet>
Assuming your inserts are done in a xxx.sql file then it is IMPORTANT you tell liquibase your SQL is formatted, you can do that by adding
--liquibase formatted sql at the top of your file
example: inserts.sql
--liquibase formatted SQL
--changeset Greg:1
insert into table1 (name, value) values ('nameOfValue', '${val1}');
References:
Example Changelogs: SQL Format and Liquibase Works with Plain Old SQL
Github demo liquibase-jpa-parameters

Is there a way to prevent insertion of duplicate rows in Hive?

I have an ORC Table. I populate it using the data from some other table as follows:
INSERT INTO TABLE orc_table_name SELECT * FROM other_table_name
Is there any way I can prevent inserting of duplicate entries into the ORC Table?
you can use not in command See a general code below: it inserts records to the orc_table_name based on the fact that value1 from TABLE_1 was not inserted before.
INSERT INTO orc_table_name
(Value1, Value2)
SELECT t1.Value1,
t1.Value2
FROM TABLE_1 t1
WHERE t1.Value1 NOT IN (SELECT Value1 FROM orc_table_name)
INSERT INTO orc_table_name(field1,field2....fieldn)
select field1,field2... field(n-1),MIN(fieldn) as fieldn
from other_table_name
Group By field1,field2...field(n-1)

How to transform a SQL record set in BLOB?

I am using an ORACLE database and I need to get the BLOB (or another LOB format) of a huge recordset (few thousands of rows), which I retrieve from a query.
I need to populate the output format as a LOB to then provide it, as input to the DBMS_CRYPTO.Hash function, which generate the hash key I need.
Is it possible to populate the LOB directly with the data of the query parsed to a JSON type? Or do you advise me to use other format to populate the (B)LOB format in an efficient way?
Thanks
The immediate answer is you can serialize to your huge recordset to XML
SELECT DBMS_XMLGEN.getxmltype ('select * from EMPLOYEE') FROM DUAL
Output:
SELECT DBMS_XMLGEN.getxmltype ('select * from EMPLOYEE') FROM DUAL
Output:
<ROWSET>
<ROW>
<EMP_ID>1</EMP_ID>
<EMP_NAME>Employee 1</EMP_NAME>
<EMP_DEPT_ID>1</EMP_DEPT_ID>
<EMP_LOC>1</EMP_LOC>
<EMP_SAL>2000</EMP_SAL>
</ROW>
<ROW>
<EMP_ID>2</EMP_ID>
<EMP_NAME>Employee 2</EMP_NAME>
<EMP_DEPT_ID>2</EMP_DEPT_ID>
<EMP_LOC>2</EMP_LOC>
<EMP_SAL>1000</EMP_SAL>
</ROW>
</ROWSET>
After that you can use to_clob or_to_blob function
SELECT TO_CLOB (DBMS_XMLGEN.getxmltype ('select * from EMPLOYEE')) FROM DUAL
output :(HUGECLOB)

Mybatis, insert in Oracle with sequence id

I have tried with this:
<insert id="insertPersonalizacionUsuario" useGeneratedKeys="true" keyProperty="param1.id" keyColumn="id">
INSERT INTO dsk_prop_personali (idpersonalizacion, idusuario, valor, centro)
VALUES (#{param1.idPersonalizacion}, #{param1.idUsuario}, #{param1.valor}, #{param2})
And with this:
<insert id="insertPersonalizacionUsuario" useGeneratedKeys="true" keyProperty="param1.id" keyColumn="id">
<selectKey keyProperty="id" resultType="int">
SELECT id.nextVal from dual
</selectKey>
INSERT INTO dsk_prop_personali (id, idpersonalizacion, idusuario, valor, centro)
VALUES (#{id}, #{param1.idPersonalizacion}, #{param1.idUsuario}, #{param1.valor}, #{param2})
But not working. Thanks
You must add the order attribute with BEFORE value to <selectKey> element. In your case you are using an Oracle database which until version 12c (review your case) it doesn't have auto-generated column types and works with a sequence is not related with your column by the rdbms.
If you take a look the documentation reference there is a section which explains your case:
MyBatis has another way to deal with key generation for databases that
don't support auto-generated column types, or perhaps don't yet
support the JDBC driver support for auto-generated keys.
Here's a simple (silly) example that would generate a random ID
(something you'd likely never do, but this demonstrates the
flexibility and how MyBatis really doesn't mind):
<insert id="insertAuthor">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1
</selectKey>
insert into Author
(id, username, password, email,bio, favourite_section)
values
(#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR})
In the example above, the selectKey statement would be run first, the
Author id property would be set, and then the insert statement would
be called. This gives you a similar behavior to an auto-generated key
in your database without complicating your Java code.
So, to be sure the selectKey statement will run first, you would need to use the Order attribute with BEFORE value, the attribute is explained very good after this example in the reference documentation:
order This can be set to BEFORE or AFTER. If set to BEFORE, then it
will select the key first, set the keyProperty and then execute the
insert statement. If set to AFTER, it runs the insert statement and
then the selectKey statement – which is common with databases like
Oracle that may have embedded sequence calls inside of insert
statements.
Therefore, you must match your keyProperty value with the insert param as you have done (keyProperty="id" will be the Param in insert statement:#{id}), and specify the resultType as int so it is a numeric sequence.
Otherwise, you must do your select using the sequence id name, in your case be sure your sequence is called id (because you are using id.NEXTVAL):
SELECT YOUR_SEQ.NEXTVAL FROM DUAL
<insert id="insertAuthor">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
select MYSEQUENCE.nextval from dual
</selectKey>
insert into Author
(id, username, password, email,bio, favourite_section)
values
(#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR}

mybatis insert all nextval unique constraint error in #transaction mdoe

MyBatis 3 spring - java
I am trying to batch insert and and getting following error when there are more then 1 records. it works perfect with one recrod
I beleive b/c it is in transaction nextval is not generating nextval on each iteration. am i correct any help on that ?
nested exception is java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (LINEAR_UPSELL.SYS_C0016697) violated
and my method has Transaction annotation in java file
#Transactional(propagation=Propagation.REQUIRED, readOnly=false, rollbackFor=Exception.class)
in mapper file following is my insert statement
<insert id="insertService" parameterType="java.util.List">
insert all
<foreach collection="list" item="ch" index="index" >
into tva_upselladmin_channel (id, source_id, service_id, name) values (
TVA_UPSELLADMIN_CHANNEL_SEQ.nextVal,
#{ch.sourceId},
#{ch.serviceId},
#{ch.name}
)
</foreach>
SELECT * FROM dual
</insert>
in oracle nextval does not work very well with insert all statement. you have to find work around as following
extractvalue(dbms_xmlgen.getxmltype('select TVA_UPSELLADMIN_CHANNEL_SEQ.nextval - 1 from dual'),'//text()')
complete insert as following have no idea with -1 is there.
<insert id="insertServiceMappings" parameterType="java.util.List">
insert all
<foreach collection="list" item="channel" index="index" >
into tva_upselladmin_channel (id, source_id, service_id, name) values (
extractvalue(dbms_xmlgen.getxmltype('select TVA_UPSELLADMIN_CHANNEL_SEQ.nextval - 1 from dual'),'//text()'),
#{channel.sourceId},
#{channel.serviceId},
#{channel.name}
)
</foreach>
SELECT * FROM dual
</insert>

Resources