DataIntegrityViolationException: Data truncation regarding PreparedStatementCallback - java

I've an issue regarding a PreparedStatementCallback which is showen as the following:
Error! Conflict [#409]: PreparedStatementCallback; SQL [EXEC de_table ?, ?, ?, ?, ?, ?, ?, ?]; Data truncation; nested exception is java.sql.DataTruncation: Data truncation
Context:
I have a section which is used to produce tables with values from my application, until recently I found there is no problem except for one of the 4 databases I was testing. The issue is that I can't see why this would be the case as I've tested it on a few other dbs and this page is working as expected. Therefore I'm assuming the code is fine, but the data isn't. I've carried out the same procedure to populate the table, but alas the error still is there.
My request URL consists of the following:
accessInd: Any
client: %
endDate: 2020-02-15 23:59:59
entDate: 2020-01-30 11:32:49
entitlementSetMode: 1
entitlementType: Historical
groupItem: %
groupType: 15
service: %
site: %
siteName: %
startDate: 2020-01-30 00:00:00
subservice: %
type: %
userLogin: %
Any the values that need to be passed into the prepared statement are the following:
exampleTable.getSite(),
exampleTable.getGroupType(),
exampleTable.getGroupItem(),
exampleTable.getService(),
exampleTable.getType(),
exampleTable.getSubservice(),
exampleTable.getEndDate(),
exampleTable.getMaxRowCount()
Does anyone know why this isn't working or any help? Futhermore the % if anyone is wondering is just used for requesting everything related to that value. Thanks.

Check if your dbs' fields type/size support the data length you are trying to put into it.
Maybe there is a slight schema difference between the three DBs that work and the one that doesn't.
Let's say yourdb.exampleTable.site field is a VARCHAR(10) and exampleTable.getSite() is "my-site-name-is-more-than-10-chars-long", that would cause this java.sql.DataTruncation exception to be thrown.

Related

JDBC Exception when setting parameters on a prepared statement

I would appreciate the help with the following:
I am getting JDBCException when setting parameters onto JDBC prepared statement.
The fragment of the query where the error is looks like this
... AND (tbl1.field1, tbl2.field2) IN ((?, ?), (?, ?)) ...
And my list of parameters is a an ArrayList of values
{123, 235689, 25,2568982}
If I run the query in the SQLDeveloper, substituting values for '?' - I get the right result
But, when running in the Java program it throws the JDBCException
An JDBC exception occurred. Statement: SELECT ... FROM .. WHERE ..AND (tbl1.field1,
tbl2.field2) IN ((?, ?), (?, ?)) .. Invalid column index
The debugger brings me to the line that does this:
statement.setLong(i, lp.longValue());
where 'statement' is a PreparedStatement ..
Your current WHERE IN tuple syntax is not valid for Oracle:
AND (tbl1.field1, tbl2.field2) IN ((?, ?), (?, ?))
This only would work on MySQL and a few other databases. You should refactor it to:
WHERE (tbl1.field1 = ? AND tbl2.field2 = ?) OR (tbl1.field1 = ? AND tbl2.field2 = ?)
Then, iterate your list of values and assign the 4 ? placeholders appropriately. As the comment above notes, your exact error could be due to an array index problem, but even if you fix that, the syntax would still fail for Oracle.

PostgreSQL query works in pgAdmin but not in Java EclipseLink

I have a SQL that counts rows per date truncate (months, days, hours). Think a history graph. Query works fine if executed in pgAdmin but fails in Java using EclipseLink.
pgAdmin query:
SELECT date_trunc( 'hour', delivered_at ),
COUNT(date_trunc( 'hour', delivered_at )) AS num
FROM messages
WHERE channel_type='EMAIL'
AND created_at>='2016-02-28 16:01:08.882'
AND created_at<='2016-02-29 16:01:08.882'
GROUP BY date_trunc( 'hour', delivered_at );
JPQL Named query
SELECT FUNCTION('date_trunc', 'hour', m.deliveredAt ),
COUNT(FUNCTION('date_trunc', 'hour', m.deliveredAt )) AS num
FROM Message m
WHERE m.channelType = :channelType
AND m.createdAt >= :fromDate
AND m.createdAt <= :toDate
GROUP BY FUNCTION('date_trunc', 'hour', m.deliveredAt )
EclipseLink debugging log:
SELECT date_trunc(?, delivered_at), COUNT(date_trunc(?, delivered_at)) FROM messages
WHERE (((channel_type = ?) AND (created_at >= ?)) AND (created_at <= ?)) GROUP BY date_trunc(?, delivered_at)
bind => [hour, hour, EMAIL, 2015-12-27 00:00:00.0, 2015-12-27 00:00:00.0, hour]
Error:
ERROR: column "messages.delivered_at" must appear in the GROUP BY
clause or be used in an aggregate function Position: 23
PostgreSQL log:
2016-03-01 13:22:08 CET ERROR: column "messages.delivered_at" must
appear in the GROUP BY clause or be used in an aggregate function at
character 23 2016-03-01 13:22:08 CET STATEMENT: SELECT date_trunc($1,
delivered_at), COUNT(delivered_at) FROM messages WHERE (((channel_type
= $2) AND (created_at >= $3)) AND (created_at <= $4)) GROUP BY date_trunc($5, delivered_at) 2016-03-01 13:22:08 CET LOG: execute
S_2: SELECT 1
If I replace the binded variables from EclipseLink logged query and execute it in pgAdmin the query works. What is going on here?
Edit: Just to clarify, it also works using em.createNativeQuery.
PostgreSQL can have trouble with resolving parameter binding, which in this case manifests as native SQL with parameters inline work, while JPA generated SQL which defaults to bound parameters fails.
One solution is to turn off parameter binding by passing "eclipselink.jdbc.bind-parameters" with a value of "false" as either a query hint for the specific query, or as a persistence unit property to turn off parameter binding by default for all queries.
On postgresql, you can use the following syntax
GROUP BY 1
That means you will group you agregate using the first selected attribute in the SELECT clause. That might be helpful there

MyBatis + PostgreSQL/PostGIS

I'm attempting to perform a radial search of database rows in a PostgreSQL database using MyBatis as an object mapper to return Java objects. Connection and all queries work as expected, except the radial search. I've installed PostGIS in the DB. Queries are set up in XML configuration files. The troublesome query is...
select * from "Events"
where (ST_DWithin("CreationLocation"::geography, ST_SetSRID(ST_Point(#{longitude}, #{latitude}), 4326)::geography, #{radius})
and "Tag" = 0 and "EventTime" >= now())
If I connect directly to the database using PGAdmin and run the query with the same parameters that are passed in to the mapper, I get multiple (correct) results. When the mapper runs the query, I get no results. I believe this has to do with the prepared statements of MyBatis but I don't know more than that.
Well I ultimately figured the issue out by changing ST_SetSRID(...) to
ST_GeogFromText('SRID=4326;POINT(' || #{longitude} || ' ' || #{latitude} || ')')
My assumption (though I haven't confirmed) is that the object mapper didn't know how to handle double-nested parameters, and it was just getting passed '?' instead of a real value for the lat and long.

How to solve bad sql grammar error with Spring JDBC?

I'm using PostgreSQL with Spring JDBC. Everythig building with Gradle:
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework:spring-jdbc")
compile("postgresql:postgresql:9.0-801.jdbc4")
compile("com.h2database:h2")
compile("com.googlecode.json-simple:json-simple:1.1")
testCompile("junit:junit")
}
Here is code fragment where I got exception:
String sql = "INSERT INTO " + dbname + " (:fields) VALUES (:values)";
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue( "fields", fieldsObj.keySet().toArray() );
parameters.addValue( "values", fieldsObj.values().toArray() );
count = jdbcTemplate.update( sql, parameters );
I get this error:
PreparedStatementCallback; bad SQL grammar [INSERT INTO test (?, ?, ?) VALUES (?, ?, ?)]; nested exception is org.postgresql.util.PSQLException
I've tried to convert array into string with values, divided by commas, but this gave me same error. What should I do? Or, if you have better ideas what to use, to build custom queries, please, post this idea in comments.
You can't use value placeholders ("?") for things that aren't values (like your field-names).
If you really want to do this, just build up the query, mapping the field-names in. Then apply the values with placeholders.
BUT do make sure you check the field-names are as you would expect and escape/quote them properly.
Oh - Not a java programmer, but do check that keySet() and values() return their results in the same order too.
Edit:
The "?" marks are value placeholders. They are used in database connection libraries of all sorts. They will be mapped to whatever parameterised query syntax the database can use. However, they only work for values - so the database can parse the query with the placeholders.

Mysql insert query not working on insert

i am getting JDBC 3.0 getParameterType call not supported exception, when trying to insert query into mysql. getting below exception
2013-10-26 20:04:25 [http-apr-8080-exec-9] DEBUG [org.springframework.jdbc.core.StatementCreatorUtils] - - JDBC 3.0 getParameterType call not supported
java.sql.SQLException: Parameter metadata not available for the given statement
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:975)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:920)
at com.mysql.jdbc.MysqlParameterMetadata.checkAvailable(MysqlParameterMetadata.java:70)
at com.mysql.jdbc.MysqlParameterMetadata.getParameterType(MysqlParameterMetadata.java:119)
at org.springframework.jdbc.core.StatementCreatorUtils.setNull(StatementCreatorUtils.java:231)
at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal(StatementCreatorUtils.java:213)
at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValue(StatementCreatorUtils.java:144)
at org.springframework.jdbc.core.ArgumentPreparedStatementSetter.doSetValue(ArgumentPreparedStatementSetter.java:65)
at org.springframework.jdbc.core.ArgumentPreparedStatementSetter.setValues(ArgumentPreparedStatementSetter.java:46)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:822)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:818)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:589)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:818)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:874)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:882)
i am using spring 3.2.4 tomcat 7 and mysql connector 5.1.26. It appears strange for me , because i have other daos which does insert and select.
when i run junit test case, i could successfully insert the data.
help needed. thanks.
EDIT- code causing the error
jdbcTemplate.update(
ADD_DATA,
new Object[] { IdKey, model.getType(), model.getUserId(), model.getDate(),
model.getPlace(), model.getArea(); ,model.getAddressBO().getCity(), model.getAddressBO().getState() });
sql query
INSERT INTO model (model_ID, model_TYPE_ID, USER_ID, model_DATE, model_PLACE, model_AREA, CITY_ID, STATE_ID) VALUES (?, ?, ? ,?, ?, ?, ? ,?) ";
the exception is misleading to debug, i fixed it, since date field is mandatory and dont accept null. i was inserting null. it worked upon giving data

Categories