ORA-00933: SQL command not properly ended In Spring batch Item Writer - spring

I am writing one spring batch based application in which i have to write a consolidated xml file data into multiple tables of database.
bean id="mysqlItemWriter"
class="org.springframework.batch.item.database.JdbcBatchItemWriter">
<property name="dataSource" ref="dataSource" />
<property name="sql">
<value>
<![CDATA[
INSERT INTO LEASE (LEASE_ID, CONTRACT_TYPE, CONTRACT_NUMBER, LEASE_AMOUNT, DESCRIPTION, CREATE_DATE, REGISTER_DATE)
VALUES ( :leaseId, :contractType, :contactNumber, :leaseAmount, :description, :leaseCreateDate, :leaseUpdateDate)
INSERT INTO CUSTOMER (CUSTOMER_ID ,FIRST_NAME, LAST_NAME, SURNAME, CUSTOMER_NUMBER, RECORD_CODE,
SOURCE_SYSTEM, BIRTH_DATE,CREATE_DATE, UPDATE_DATE,ADDRESS,STREET,HOUSE_NUMBER,
STATE, POSTAL_CODE, COUNTRY_CODE )
VALUES ( :customerId , :firstname, :lastName ,:surname, :customerNumber, :recordCode, :SourceSystem,
:birthDate, :leaseCreateDate, :leaseUpdateDate, :address, :houseNumber, :city, :state, :postalcode,
:countryCode)
]]>
</value>
In the above code when only one SQL statement is there it is working fine but for two insert statements it is not working fine. It is giving the error as
"ORA-00933: SQL command not properly ended" .
When i am inserting ; after first insert statement it is showing the same error
I am not able to resolve this..

You can always try wrapping your 2 statements inside a PL/SQL anonymous block (Make sure you don't forget any of the required semi colons).
begin
insert into ...;
insert into ...;
end;
Technically, it should then be treated as a single statement and should work.
bean id="mysqlItemWriter"
class="org.springframework.batch.item.database.JdbcBatchItemWriter">
<property name="dataSource" ref="dataSource" />
<property name="sql">
<value>
<![CDATA[
begin
INSERT INTO LEASE (LEASE_ID, CONTRACT_TYPE, CONTRACT_NUMBER, LEASE_AMOUNT, DESCRIPTION, CREATE_DATE, REGISTER_DATE)
VALUES ( :leaseId, :contractType, :contactNumber, :leaseAmount, :description, :leaseCreateDate, :leaseUpdateDate);
INSERT INTO CUSTOMER (CUSTOMER_ID ,FIRST_NAME, LAST_NAME, SURNAME, CUSTOMER_NUMBER, RECORD_CODE,
SOURCE_SYSTEM, BIRTH_DATE,CREATE_DATE, UPDATE_DATE,ADDRESS,STREET,HOUSE_NUMBER,
STATE, POSTAL_CODE, COUNTRY_CODE )
VALUES ( :customerId , :firstname, :lastName ,:surname, :customerNumber, :recordCode, :SourceSystem,
:birthDate, :leaseCreateDate, :leaseUpdateDate, :address, :houseNumber, :city, :state, :postalcode,
:countryCode);
end;
]]>
</value>

There is a good description of the issue here:
http://forum.liquibase.org/topic/formatted-sql-enddelimiter-issue
I suggest adding the "/" to see if that works in combination with
endDelimiter:/ or using splitStatement:false

Related

Why can't I save it to Database

Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "PRODUCT" not found (this database is empty); SQL statement: insert into product (price, product_name, url, year, id) values (?, ?, ?, ?, ?) [42104-214]
I think it's so clear print the error: Table "PRODUCT" not found
You can set a flag to auto-generate the database for you in your persistence xml
<property name="jakarta.persistence.schema-generation.database.action" value="drop-and-create" />
or
<property name="hibernate.hbm2ddl.auto" value="drop-and-create" />

XML datatype in column to find existing of values

I have issues in find the rows in table having datatype as XMLType and I am looking for Name 'PrimeSub' and Value as 'Y'. Thanks
<attributes>
<upper_lvl_ver_desc>
<Name>AABB</Name>
<Description>pkListValue</Description>
<Value/>
</upper_lvl_ver_desc>
<upper_lvl_ver_desc>
<Name>GL_PS_ALLOWED</Name>
<Description>pkListValue</Description>
<Value/>
</upper_lvl_ver_desc>
<upper_lvl_ver_desc>
<Name>PrimeSub</Name>
<Description>pkListValue</Description>
<Value>Y</Value>
</upper_lvl_ver_desc>
</attributes>
You didn't post your table name or structure, so here I'm using mytable as the table name and xmlcol as the xmltype column. The WITH clause at the top is just to provide the test data.
with mytable as (select xmltype('<attributes>
<upper_lvl_ver_desc>
<Name>AABB</Name>
<Description>pkListValue</Description>
<Value/>
</upper_lvl_ver_desc>
<upper_lvl_ver_desc>
<Name>GL_PS_ALLOWED</Name>
<Description>pkListValue</Description>
<Value/>
</upper_lvl_ver_desc>
<upper_lvl_ver_desc>
<Name>PrimeSub</Name>
<Description>pkListValue</Description>
<Value>Y</Value>
</upper_lvl_ver_desc>
</attributes>') as xmlcol from dual)
-- query starts here
select xmlcol
from mytable
inner join XMLTable('/attributes/upper_lvl_ver_desc' PASSING mytable.xmlcol
COLUMNS c_name varchar2(50) PATH 'Name',
c_value varchar2(1) PATH 'Value') atts
on c_name = 'PrimeSub' and c_value = 'Y'
;
This method might seem a bit counter-intuitive, but it's one way Oracle recommends doing it. You join the XML column as a pseudo-table using the XMLTable function, transforming it into relational data which can easily be manipulated in SQL. You can read more about it here.

mybatis batch insert generating duplicate uuid primary key

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>

Unique constraint violation on insertion after server restart

I am running a JBoss EAP 7 server with an Oracle 11g DB, and Hibernate for JPA. I have noticed something weird. When I first create the database and start the server, everything works fine. I send requests from the client and the server persists the data in the DB.
If I restart the server and try to do the same, I get a unique constraint violation exception for every request:
java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (SCHEMA.SYS_C0010299) violated
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:951)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:513)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:227)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:208)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1046)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1336)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3613)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3694)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1354)
at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:537)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204)
I checked the constraint in sqlplus with the query below. (I ran the query as the system user, not the same user as the server, if that matters).
SELECT A.TABLE_NAME,C.TABLE_NAME,COLUMN_NAME FROM ALL_CONS_COLUMNS A
JOIN ALL_CONSTRAINTS C ON A.CONSTRAINT_NAME = C.CONSTRAINT_NAME
WHERE C.CONSTRAINT_NAME = 'SYS_C0010299';
It seems to happen on the primary key of one of my tables. That primary key is generated with a sequence.
#Id
#Column(name="ID_COL")
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "SEQ_NAME_GEN")
#SequenceGenerator(name = "SEQ_NAME_GEN", sequenceName = "SEQ_NAME")
private Long id;
If I create a fresh new DB, the application again works fine at first, until I restart the server. Why does this happen?
This is the relation of the entity class to another entity class:
// other class
#OneToMany(cascade=CascadeType.ALL, mappedBy="otherClass")
#MapKey(name = "mapKey")
private Map<MapKey, ConstraintViolationEntityClass>
map;
// problematic class (ConstraintViolationEntityClass)
#Column(name = "MAP_KEY")
#Enumerated(EnumType.ORDINAL)
private EnumType enumType;
#ManyToOne
#JoinColumn(name = "OTHER_CLASS_ID", nullable = false)
private OtherClass otherClass;
And this is the SQL code I used to create the table for the ConstraintViolationEntityClass:
create table schema.ConstraintViolationEntityTable (
id_col number(10) not null primary key,
map_key number(2) not null,
other_class_id number(10) not null,
constraint other_class_fk foreign key (other_class_id) references schema.other_class(id)
);
This is my persistence.xml:
<persistence-unit name="unit1" transaction-type="JTA">
<jta-data-source>java:jboss/OracleDS</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform"/>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="validate" />
</properties>
</persistence-unit>
For some reason, some of the primary keys of the rows inserted by the successful requests are negative. And checking dba_sequences, the last_number of the sequence is 43, even though the table only has 24 rows in it (12 rows added per client request)
As stated in the answer that PeterM linked to, the default allocation size for sequence generators is 50, which is the root cause of the problem, since you defined the sequence with an increment of 1. I'll just comment on the negative values issue.
An allocation size of 50 (set in SequenceGenerator.allocationSize) means that Hibernate will:
create the sequence with INCREMENT BY 50 (if you let it)
grab the next value n from the sequence
start allocating ids from n-50 till n
repeat the two steps above once it runs out of numbers
Since you've made the sequence increment by 1, it's easy to see where the negative values come from (and why constraint violations will follow). If you tried inserting more than 50 rows, you'd run into constraint violations without having to restart the server.

How can I generate response after insert query in wso2dss?

I am using wso2dss.
I just insert one row.
Table has only one field and it is not the unique and it is not a key.
I can't use the "GenerateKeys" option.
However, I need to generate response after insert query is success in the wso2dss.
I created table as below.
create table SAMPLETABLE (My_VALUE VARCHAR (100));
<data name="MyTESTSERVICE">
<config id="testconfig">
<property name="username">sa</property>
<property name="password">sa</property>
<property name="url">jdbc:h2:tcp://localhost/~/test;MODE=Oracle</property>
<property name="driverClassName">org.h2.Driver</property>
</config>
<query id="insertMyValue" useConfig="testconfig">
<sql>INSERT INTO SAMPLETABLE (My_VALUE) VALUES (:MyValue)</sql>
<param name="MyValue" sqlType="STRING"/>
</query>
<operation name="insertOP">
<call-query href="insertMyValue">
<with-param name="MyValue" query-param="MyValue"/>
</call-query>
</operation>
</data>
It was working without any response.
But I need customized response after inserting is successful. How can I do?
You can try stored procedures that return value. ie you can write sp which is insert values in database and returns the status of transaction, in dss it returns that whether your query ran on DB or not.

Resources