Java/Hibernate + HSQLDB java.sql.BatchUpdateException: data exception: string data, right truncation - java

I am testing an application locally using a memory-based HSQLDB.
So far everything went fine, however, when executing a testcase with a String bigger than 256 chars I ran into an error.
Caused by: java.sql.BatchUpdateException: data exception: string data, right truncation; table: TABLENAME column: COLNAME
at org.hsqldb.jdbc.JDBCPreparedStatement.executeBatch(Unknown Source)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
... 30 more
I gathered that the cause of this error is usually an "overflow" of the datatype one is using.
What bothers me is that I explicitly defined the column to be 4000 chars big, using the hbm.xml files.
<property name="translation" type="java.lang.String" length="4000">
<column name="COLNAME" not-null="false" />
</property>
When I cut the test string down to 256 chars or less everything starts working again. 257+ chars and the error is thrown. I don't really see the reason why this is happening. Why would HSQLDB define this column as length="256", when I explicitly state that it's supposed to be 4000...
Can anyone help?
Best regards,
daZza

Well, for whatever reason HSQLDB seems to do a bad mapping for certain types and values specified in the config file to the real tables it creates.
I was able to fix the issue by changing the "type" attribute to type=text. Now everything works perfectly. I just hope that after I finish testing the application it still works with the original MSSQL DB and maps text to a varchar then...

Related

Oracle->MSSQL: How to set identifier generator?

I'm migrating OracleDB11g to MSSQL2014.
Currently getting following error when trying to save new data:
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Cannot
insert the value NULL into column 'ID', table 'testDB.FILE_SETTINGS';
column does not allow nulls. INSERT fails.
My interpretation is that this is caused as the "native" ID generator differs between Oracle & MSSQL (Sequence vs. Identity).
In Oracle we had small customization to HIBERNATE_SEQUENCE:
alter sequence hibernate_sequence increment by 5;
...but thats all.
hibernate-mapping is originally like this:
<id name="id" column="ID" type="java.lang.Long">
<generator class="native">
</generator>
</id>
In MSSQL I have tried it like this with no luck:
<id name="id" column="ID" type="java.lang.Long">
<generator class="sequence">
<param name="sequence">HIBERNATE_SEQUENCE</param>
</generator>
</id>
And in MSSQL server I have sequence (migration tool created):
HIBERNATE_SEQUENCE in testDB->Views->sys.sequences
Also found in (migration tool created):
testDB->Views->INFORMATION_SCHEMA.SEQUENCES
How should this be done properly as I want to retain the same way to generate identity as was in Oracle? Something wrong in MSSQL or in hibernate settings?
Hibernate version is quite old: 2.1.8
Your interpretation of the error is wrong. This error tells you nothing about sequence. It tells you that your testDB.FILE_SETTINGS has id column defined as NOT NULL but you try to insert NULL value here.
I don't see your code but I think there is something like this:
create table dbo.MyTbl_wrong (id int NOT NULL, col1 varchar(100) );
insert into dbo.MyTbl_wrong(col1) values ('1 str'), ('2 str'), ('3 str');
Cannot insert the value NULL into column 'id', table
'db2.dbo.MyTbl_wrong'; column does not allow nulls. INSERT fails. The
statement has been terminated.
What you should do instead is to use sequence in the default for your id column like this:
create sequence dbo.MySeq
start with 1;
create table dbo.MyTbl (id int NOT NULL default(next value for dbo.MySeq), col1 varchar(100) );
insert into dbo.MyTbl(col1) values ('1 str'), ('2 str'), ('3 str');
--select *
--from dbo.MyTbl;
-------
--id col1
--1 1 str
--2 2 str
--3 3 str
Answering own question if some day someone has similar issues:
Apparently there was nothing wrong with the settings I mentioned in original question, only that hibernate 2.1.8 seemed not to support the SEQUENCE id genererator. Also old hibernate obviously did not support the needed SQLServer2012Dialect.
Ended up updating the hibernate version to 4.3.11 (with its dependencies). This version got selected as it required the least amount of refactoring.
I had some issues with the dependencies as this old project was not using Maven.
Also faced this error as any DB query was attempted:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
I found out that new hibernate version was defaulted to use lazy loading which was not supported in the old version. So I ended up fixing it with setting "lazy=false" in hibernate setting files.
You may see "org.hibernate.LazyInitializationException: could not initialize proxy - no Session" while upgrading from hibernate 2.1 to hibernate 3.0. You will suddenly find yourself puzzling what happened, it was working before update. Reasons is, Hibernate 3 introduced lazy loading as the default i.e. lazy="true". If you want it to work the same as before you can mark everything as lazy="false". Alternatively you'll have to start eagerly initialising your entities and associations.
Read more: http://javarevisited.blogspot.com/2014/04/orghibernatelazyinitializationException-Could-not-initialize-proxy-no-session-hibernate-java.html#ixzz56ahBmiBl

DBUnit: dataset with MySQL YEAR type column

folks!
I'm having a problem using DBUnit:
In my test class, when I call DatabaseOperation.INSERT.execute(connection, dataSet), using a FlatXmlDataSet referencing a table that contains a column of type YEAR(4) - MySQL - I get the following:
(...)
Caused by: org.dbunit.dataset.datatype.TypeCastException: Error casting value for table 'Vehicle' and column 'LaunchYear'
at org.dbunit.operation.AbstractBatchOperation.execute(AbstractBatchOperation.java:210)
at net.carroramafleet.ws.utils.DbUnitHelper.execute(DbUnitHelper.java:57)
... 33 more
Caused by: org.dbunit.dataset.datatype.TypeCastException: Unable to typecast value <2010> of type <java.lang.String> to DATE
at org.dbunit.dataset.datatype.DateDataType.typeCast(DateDataType.java:110)
at org.dbunit.dataset.datatype.DateDataType.setSqlValue(DateDataType.java:141)
at org.dbunit.database.statement.SimplePreparedStatement.addValue(SimplePreparedStatement.java:73)
at org.dbunit.database.statement.AutomaticPreparedBatchStatement.addValue(AutomaticPreparedBatchStatement.java:63)
at org.dbunit.operation.AbstractBatchOperation.execute(AbstractBatchOperation.java:200)
... 34 more
Here's my dataset:
<dataset>
<Vehicle
ID="999"
LaunchYear="2010" />
</dataset>
As I have mentioned above, I have a YEAR(4) type column, LaunchYear, in the table Vehicle. And DBUnit can't insert this row because of this information can't be converted correctly.
I've already tried to replace this information using DBUnit's ReplacementDataSet, but I still have problem with TypeCastException. I really can't set a valid YEAR-formatted information.
Could somebody help me?
Thanks,
Jeff
This question is a bit old but I thought I would reply as I just ran into this same issue today.
I believe this is a bug in DbUnit. BTW, I'm using 2.4.9 but did check the release notes for later releases to see if this is mentioned as a bug fix.
The YEAR column is being converted into a java.sql.Date object. The initial bug is that there is no conversion from a simple string "2016" to a java.sql.Date. That leads to the TypeCastException. Changing this field to something like "2016-08-10" gets you past this initial error but leads to a SQLException when MySql attempts to truncate the Date into a integer or short.
The only way I have been able to work around this is to add specific code in the #SetUp or #Before methods to populate the table with initial data.

OpenJPA Syntax error: Encountered "optimize"

When using OpenJPA to execute a select statement in in-memory database org.apache.derby, I encounter this error:
javax.ejb.EJBException: The bean encountered a non-application exception; nested exception is:
<openjpa-2.1.2-SNAPSHOT-r422266:1636464 fatal general error> org.apache.openjpa.persistence.PersistenceException: Syntax error: Encountered "optimize" at line 1, column 80. {SELECT t0.VERSION, t0.SOMEOTHER_COLUMN FROM MYTABLE t0 WHERE t0.MYTABLE_CODE = ? optimize for 1 row} [code=20000, state=42X01] FailedObject: UDA [org.apache.openjpa.util.StringId] [java.lang.String]
The OpenJPA client is embedded in a IBM WebSphere client: com.ibm.ws.jpa.thinclient-8.5.5.5.jar
Apparently OpenJPA adds the 'optimize for 1 row' part because it thinks it is dealing with DB2? How could this be possible? Is there any way I can turn off this feature explicitly?
I did find some explanation on the 'optimize for 1 row' postfix:
https://www.ibm.com/developerworks/community/blogs/22586cb0-8817-4d2c-ae74-0ddcc2a409bc/entry/optimize_for_1_row1?lang=en
Apparently OpenJPA adds the 'optimize for 1 row' part because it thinks it is dealing with DB2? How could this be possible? Is there any way I can turn off this feature explicitly?
With the information provided, I'm not sure why this is the case.
Fortunately, you can override this with the following property in your persistence.xml:
<property name="openjpa.jdbc.DBDictionary" value="derby"/>
Solved it. The application has derby configured, but it is using a data access service which in turn had db2 specified as the DB dictionary.
I am servicing on existing code and therefore could not find that setting right away. Thank you both for pointing me in the right direction.

Hibernate slqjdbc4 column with spaces

I need to map in Java with hibernate a table in sqlserver that has spaces in the column names.
I use Sqlserver 2008 jre7 com.microsoft.sqlserver.sqljdbc4 with Hibernate 3.3.2
I found a lot of similar questions in different forums but none of the solutions I read worked.
I tried using the backtick
<property name="nameSpaces" type="string" >
<column name="`Name with spaces`" not-null="false" />
</property>
this is the error
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near '`'.
I also tried to use the [] brakets but hibernate converted it in ` again.
<column name="[Name with spaces]" not-null="false" />
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near '`'.
Finally I also tried both of them
<column name="`[Name with spaces]`" not-null="false" />
or
without success.
Can someone help me? Is there any hibernate configuration I can change to work with these column names.
Thanks
The answer (by BilalDja) is hidden above in a comment. I found his answer helpful so I thought I would add the answer here for others with the same problem.
This issue is hard to debug, I had to dig really deep into the hibernate and jdbc code to finally find the "real" SQL statement that is created to get data from the database. I then copied its value and ran it manually on my SQL Server database. Straight away the syntax error was obvious and sure enough it was cause by a space in a column name.
To fix this I just escaped the double quotes around the problematic column name as explained in BilalDja's comments and expanded slightly here...
#Column(name = "\"Column name\"")
private String variableColumnWillMapTo;
That's it, problem solved, no more syntax error.

Hibernate mapped property to SQL formula fails after update to 3.6.5

I have just updated to Hibernate 3.6.5.Final from 3.3.0.GA and have run into a problem with a SQL formula call on an XML mapped property:
<property
name="endDate"
type="java.util.Date"
formula="TIMESTAMPADD(SECOND, (quantity*60*60), transactionDate)"
/>
I have changed nothing in the *.xml.hbm nor have I changed the database design. Where previously my endDate was nicely calculated I now get a MySQLSyntaxErrorException:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'this_.SECOND,(this_.quantity*60*60),this_.transactionDate) as formula0_0_ from t' at line 1
The problem is pretty obvious in that the this_.SECOND should be SECOND. It seems to me that Hibernate recognizes the TIMESTAMPADD as a formula but not the SECOND as a static passed parameter and thinks it thus must be a column in the table. I am unsure how to tell hibernate it should use SECOND as is.
I've tried registerFunction and registerKeyword on my Dialect but without any luck as these seem related to HQL function definitions and not native SQL which is used here in the formula.
Could anyone point me in the right direction or tell me what Hibernate does different between these versions and how I can fix it?
I just upgraded to Hibernate 4.1.2 and this same problem started coming back. The solution of [SECOND] no longer works and I had to register the keyword in my own custom Dialect. Like:
public class ExtendedMySQL5InnoDBDialect extends MySQL5InnoDBDialect {
public ExtendedMySQL5InnoDBDialect() {
super();
//make sure to register it in lowercase as uppercase does not work (took me 4 hours to realize)
registerKeyword("second");
}
}
I had the same type of problem in Sql Server - a similar solution might work. .
Here is what I found. .
https://forum.hibernate.org/viewtopic.php?p=2427791
So, try putting quotes around SECOND
<property
name="endDate"
type="java.util.Date"
formula="TIMESTAMPADD("SECOND", (quantity*60*60), transactionDate)"
/>
I am actually not sure how you would escape double quotes in this xml attribute, but I would try " first and if that doesn't work \"

Categories