Insert timestamp with JdbcTemplate in Oracle database ( ORA-01858 ) - oracle

I've read a lot of stuff about this error, and still not found the mistake.
I'm using JdbcTemplate to insert a row in some table with some timestamp column
I'm pretty sure the timestamp is the problem, as if delete from the insert it works fine)
My code:
private static final String INSERT_CITAS = "INSERT INTO CITAS ("
+ "idCita, idServicio, " + "fechaCita, "
+ "idEstado, idUsuarioInicial) " + "VALUES (?, ?, ?, ?, ?)";
Object[] params = {
idCita,
citaQuenda.getIdServicio(),
getDateToDBFormat(citaQuenda.getFechaCita()),
ESTADO_INICIAL,
USUARIO_INICIAL };
String queryCitas = INSERT_CITAS;
super.getJdbcTemplate().update(queryCitas, params);
protected String getDateToDBFormat(Date fechaCreacion){
return "TO_TIMESTAMP('" +
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(fechaCreacion)
+ "', 'yyyy-mm-dd hh24:mi:ss')" ;
}
And having the next error:
org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [INSERT INTO citas_55 (idCita, idServicio, fechaCita, idEstado, idUsuarioInicial) VALUES (?, ?, ?, ?, ?)];
ORA-01858: a non-numeric character was found where a numeric was expected
I've tried to execute the sql in some SQL editor having success, so I can't be more confused.
Being my params: [461, 100, TO_TIMESTAMP('2015-01-28 00:00:01', 'yyyy-mm-dd hh24:mi:ss'), 1, 8888] This actually works.
INSERT INTO citas (idCita, idServicio, fechaCita, idEstado, idUsuarioInicial) VALUES (457, 100, TO_TIMESTAMP('2015-01-28 00:00:01', 'yyyy-mm-dd hh24:mi:ss') , 1, 8888);
Any kind of help would be appreciated. Thanks in advance!

Don't convert back and forth between dates/timestamps and Strings.
Just pass a java.sql.Timestamp instance as a parameter:
Object[] params = {
idCita,
citaQuenda.getIdServicio(),
new java.sql.Timestamp(citaQuenda.getFechaCita()),
ESTADO_INICIAL,
USUARIO_INICIAL };
String queryCitas = INSERT_CITAS;
super.getJdbcTemplate().update(queryCitas, params);

I will go out on a limb here, and think I may see the problem. getDateToDBFormat() method is returning a String type, which contains the text, "TO_TIMESTAMP(...)". That is not a date or timestamp parameter. It is a string parameter. You need to do this instead:
Remove the TO_TIMESTAMP stuff from getDateToDBFormat() and have it just return the formatted DATE/TIME value (the format you show is not an oracle timestamp, but a DATE type).
change your insert to:
"INSERT INTO CITAS ... VALUES (?, ?, TO_DATE(?,?) , ?, ?)"
Where the parameters to the TO_DATE call are the return from getDateToDBFormat() and the second parameter is the date format mask. However, can't you just get rid of that mess and bind a Java Date type (or jdbc sql equivalent) directly?
That should work.

Related

JdbcPagingItemReader Spring batch skipping last element

I have a table with this structure:
CNMA_CO_PLATFORM_MESSAGE|AUDI_TI_CREATION|FIELD4|OTHER FIELDS
test-jj#2774#20210422112434957#00026129|22/04/21 11:24:34,957000000|11|..
test-jj2#2774#20210422112434957#00026129|22/04/21 11:24:34,957000000|12|..
test-jj3#2774#20210422112434957#00026129|22/04/21 11:24:34,957000000|13|..
This combination is the PRIMARY_KEY of the table:
CNMA_CO_PLATFORM_MESSAGE|AUDI_TI_CREATION
Well, I have an JdbcPagingItemReader defined like this (Pagesize is 1):
#StepScope
#Bean
public JdbcPagingItemReader<PendingNotificationDTO> pendingNotificationReader(
#Value("#{stepExecution}") StepExecution stepExecution){
final JdbcPagingItemReader<PendingNotificationDTO> reader = new JdbcPagingItemReader<>();
reader.setDataSource(daoDataSource);
reader.setName("pendingNotificationReader");
//Creamos la Query
final OraclePagingQueryProvider oraclePagingQueryProvider = new OraclePagingQueryProvider();
oraclePagingQueryProvider.setSelectClause("SELECT " +
" cegct.AUDI_TI_CREATION, "+
" CNMA_CO_PLATFORM_MESSAGE, " +
" OTHERFIELDS... ");
oraclePagingQueryProvider.setFromClause("FROM TABLE1 cegct " +
" JOIN TABLE1 notip ON cegct.field1 = notip.field1 " +
" AND notip.field2 = :frSur ");
oraclePagingQueryProvider.setWhereClause("WHERE "
+ " cegct.field3 = 0 "
+ " AND cegct.field4 in (:notifStatusList) ");
//Indicamos conjunto de campos no repetibles para poder paginar
Map<String, Order> sortKeys = new HashMap<>();
sortKeys.put("CNMA_CO_PLATFORM_MESSAGE", Order.DESCENDING);
sortKeys.put("AUDI_TI_CREATION", Order.DESCENDING);
oraclePagingQueryProvider.setSortKeys(sortKeys );
reader.setQueryProvider(oraclePagingQueryProvider);
String frSur = stepExecution.getJobExecution().getExecutionContext().getString(Constants.FM_ROLE_SUR_ZK);
String notifStatus = stepExecution.getJobExecution().getExecutionContext().getString(Constants.STATUS_REPORTS);
Map<String, Object> parameters = new HashMap<>();
parameters.put("frSur", frSur);
parameters.put("notifStatusList", Arrays.asList(StringUtils.split(notifStatus, ",")));
reader.setParameterValues(parameters );
Integer initLoaded = stepExecution.getJobExecution().getExecutionContext().getInt(Constants.RECOVER_PENDING_NOT_COMMIT);
reader.setPageSize(initLoaded);
reader.setRowMapper(new BeanPropertyRowMapper<PendingNotificationDTO>(PendingNotificationDTO.class));
return reader;
}
(I hide some irrelevant fields and table names)
Well, I run a test and my 3 records are valid to the select, these are selected one to one by the page size. Anyway, the first chunk-reader generated select my "test-jj3#..." record, my second chunk-reader select "test-jj2#.." and my third chunk-reader doesn't select doesn't recover any record (It should recover last 'test-jj#...' element.
These are the generated sqls (I hide some sensible no relevant fields)
First chunk, Select 1 register
SELECT * FROM (
SELECT
cegct.AUDI_TI_CREATION
CNMA_CO_PLATFORM_MESSAGE, [otherfields]
FROM [FROM]
WHERE [where]
ORDER BY CNMA_CO_PLATFORM_MESSAGE DESC, AUDI_TI_CREATION DESC
) WHERE ROWNUM <= 1;
Second chunk, Select 1 register (Here, the rownum filter by the sortkeys)
SELECT * FROM (
SELECT
cegct.AUDI_TI_CREATION
CNMA_CO_PLATFORM_MESSAGE, [otherfields]
FROM [FROM]
WHERE [where]
ORDER BY CNMA_CO_PLATFORM_MESSAGE DESC, AUDI_TI_CREATION DESC
) WHERE
ROWNUM <= 1 AND (
(CNMA_CO_PLATFORM_MESSAGE < 'test-jj3#2774#20210422112434957#00026129')
OR
(CNMA_CO_PLATFORM_MESSAGE = 'test-jj3#2774#20210422112434957#00026129' AND AUDI_TI_CREATION < TO_DATE('2021-04-22 11:24:34', 'YYYY-MM-DD HH24:MI:SS'))
);
Third chunk, select 0 registers
SELECT * FROM (
SELECT
cegct.AUDI_TI_CREATION
CNMA_CO_PLATFORM_MESSAGE, [otherfields]
FROM [FROM]
WHERE [where]
ORDER BY CNMA_CO_PLATFORM_MESSAGE DESC, AUDI_TI_CREATION DESC
) WHERE
ROWNUM <= 1 AND (
(CNMA_CO_PLATFORM_MESSAGE < 'test-jj2#2774#20210422112434957#00026129')
OR
(CNMA_CO_PLATFORM_MESSAGE = 'test-jj2#2774#20210422112434957#00026129' AND AUDI_TI_CREATION < TO_DATE('2021-04-22 11:24:34', 'YYYY-MM-DD HH24:MI:SS'))
);
Sorry for my english, I hope you can understand my problem.
Logs for the Prepared SQL Statement
Executing prepared SQL statement [SELECT * FROM (
SELECT
cegct.AUDI_TI_CREATION,
CNMA_CO_PLATFORM_MESSAGE,
OTHERFIELDS...
FROM TABLE1 cegct
JOIN TABLE2 notip ON cegct.field1 = notip.field1
AND notip.field2 = ?
WHERE cegct.field3 = 0
AND cegct.field4 in (?, ?, ?)
ORDER BY CNMA_CO_PLATFORM_MESSAGE DESC, AUDI_TI_CREATION DESC) WHERE ROWNUM <= 1]
20221116 12:52:43.560 TRACE org.springframework.jdbc.core.StatementCreatorUtils [[ # ]] - Setting SQL statement parameter value: column index 1, parameter value [1], value class [java.lang.String], SQL type unknown
20221116 12:52:43.560 TRACE org.springframework.jdbc.core.StatementCreatorUtils [[ # ]] - Setting SQL statement parameter value: column index 2, parameter value [11], value class [java.lang.String], SQL type unknown
20221116 12:52:43.560 TRACE org.springframework.jdbc.core.StatementCreatorUtils [[ # ]] - Setting SQL statement parameter value: column index 3, parameter value [12], value class [java.lang.String], SQL type unknown
20221116 12:52:43.560 TRACE org.springframework.jdbc.core.StatementCreatorUtils [[ # ]] - Setting SQL statement parameter value: column index 4, parameter value [13], value class [java.lang.String], SQL type unknown
A bind variable is a single value; therefore when you use:
AND cegct.field4 in (:notifStatusList)
Then :notifStatusList is a single string and is NOT a list of values and you effectively doing the same as:
AND cegct.field4 = :notifStatusList
If the bind variable :notifStatusList is a single value then it will work; however, when you try to pass in multiple values then it will not match those multiple values but will try to match field4 to the entire delimited list (which fails and will filter out all the rows).
If you want to pass a delimited string then use:
AND ',' || :notifStatusList || ',' LIKE '%,' || cegct.field4 || ',%'
Alternatively, pass the values as an array (rather than a delimited string) into an Oracle collection and then test to see if it is in that collection.

Inserting the Date from JSpinner Component into Oracle DB in the correct format

So I've been trying to insert the date from a JSpinner component into an Oracle DB.
The date format of a sample entry in the Oracle table is like "2018-01-01 09:30:00.0" (image for reference):
I want to save the value obtained from the JSpinner in the same format as otherwise, I'm getting a Unparseable date exception.
For reference this is the date I enter in the spinner :
and this is the error that shows up :
This is the code I'm using to try and insert it into the Oracle DB:
TimeReserved = jSpinner1.getValue().toString();
String Query = "Insert into RoomTable Values( ?, ?, ?)";
PreparedStatement stmt = conn.prepareStatement(Query);
//setting Date
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd hh-mm-ss a" );
Date fd = formatter.parse(TimeReserved);
java.sql.Date sqlDate = new java.sql.Date(fd.getTime());
stmt.setDate(2, sqlDate);
Additionally, I've set the editor property up like this :
Thank you guys for your help in advance :)

PreparedStatement - Missing IN or OUT parameter at index - only if use clearParameters()

I'm using Oracle 10; this is my code
String insertEntityItemQuery = " INSERT INTO My_schema.ENTITYITEM (ENTITYITEMID, ENTITYID, FASCICOLOID, CALLERID, PARENTENTITYITEMID) " +
" VALUES ((My_schema.ENTITYITEMIDSequence.NEXTVAL), ? , ?, ?, ?) " ;
PreparedStatement preparedStatement = conn.prepareStatement(insertEntityItemQuery , new String[]{"ENTITYITEMID"} );
preparedStatement.clearParameters();
preparedStatement.setInt(1, entityId);
preparedStatement.setString(2, fascicoloID);
preparedStatement.setString(3, callerID);
preparedStatement.setInt(4, parentEntityItemId);
preparedStatement.executeQuery();
I get
java.sql.SQLException: Missing IN or OUT parameter at index:: 5
but only if I use clearParameters() method, if I comment it the execution goes fine!!
It seems that clearParameters resets the My_schema.ENTITYITEMIDSequence.NEXTVAL
param, but how it is possible?

Inconsistent datatypes: expected DATE got NUMBER - when inserting into DB

I'm trying to insert a row in a DB table and I keep getting
ORA-00932: inconsistent datatypes: expected DATE got NUMBER
I don't know why this is happening since all dates are SYSDATE
String insertNewAlarmStat =
"insert into alarmes (id_alarm, alarm_key, id_notif, sever, urgency, date_hour_start, date_hour_modif, date_hour_end, " +
"state, state_rec, date_hour_rec, id_user_rec, id_system_rec, " +
"type, cause, " +
"num_events, id_entity_g, type_entity_g, " +
"desc_entity_g, problem, " +
"time_urg_act, max_urg_act, time_end, time_arq, lim, rec_oblig, dn, num_events_ps, id_alarm_o, id_notif_o, text_ad, domain, date_hour_reg) " +
"values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, SYSDATE, SYSDATE, SYSDATE, SYSDATE, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, SYSDATE)";
PreparedStatement prpstmt = null ;
try {
prpstmt = conn.prepareStatement(insertNewAlarmStat);
prpstmt.setInt(1, randomNumberGenerator());
prpstmt.setString(2, UUID.randomUUID().toString());
prpstmt.setString(3, UUID.randomUUID().toString());
prpstmt.setInt(4, randomNumberGenerator());
prpstmt.setInt(5, 8);
prpstmt.setInt(6, 8524);
prpstmt.setString(7, UUID.randomUUID().toString());
prpstmt.setString(8, UUID.randomUUID().toString());
prpstmt.setString(9, UUID.randomUUID().toString());
prpstmt.setString(10, UUID.randomUUID().toString());
prpstmt.setString(11, "KABOOM");
prpstmt.setInt(12, 8);
prpstmt.setInt(13, 43);
prpstmt.setString(14, UUID.randomUUID().toString());
prpstmt.setString(15, UUID.randomUUID().toString());
prpstmt.setString(16, UUID.randomUUID().toString());
prpstmt.setString(17, UUID.randomUUID().toString());
prpstmt.setInt(18, 2);
prpstmt.setInt(19, 224);
prpstmt.setInt(20, 2);
prpstmt.setInt(21, 224);
prpstmt.setInt(22, 2);
prpstmt.setInt(23, 224);
prpstmt.setInt(24, 2);
prpstmt.setString(25, UUID.randomUUID().toString());
prpstmt.setString(26, UUID.randomUUID().toString());
prpstmt.setString(27, UUID.randomUUID().toString());
prpstmt.setInt(28, 2);
prpstmt.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I've tryed this way and I've tryed to remove the SYSDATE's and add some:
prpstmt.setDate(number, getCurrentDate()); //getCurrent date returns sql.Date
However, the error is the same
I've been debugging for some time now and I can't seem to find the problem, what am I missing?
Check the position of your columns compared to the values you are sending for datatype agreement.

VB6, RDO AND QUERYSTRING

I'm creating a query string as follows ...
gSql = "{ CALL MYSP( ?, ?, ?, ?, ?, ?, {resultset 10, RECORD_OUTPUT} ) }"
the {resultset 1000, RECORD_OUTPUT} is copied it from Microsoft's MSDN
The error displayed after I compile is:
identifier \'RECORD_OUTPUT\' must be declared
What should the {resultset 1000, RECORD_OUTPUT} actually be ?
At this position, The Stored Procedure will return refcursor back to VB6.

Resources