The following change to IncrementGenerator.java
revision 1.11
date: 2005/04/26 06:37:53; author: oneovthafew; state: Exp; lines: +24 -5
TODO-173, increment for union-subclass
SQL logging from id generators
----------------------------
seems to have broken this generator when used on tables with blanks in their names.
This update tries to allow access to a comma-separated list of tables to identify the currently max-value of an id column.
I have a with the following mapping (in extract):
<hibernate-mapping>
<class name="dk.statsbiblioteket.navision.integration.Transaction" table="`REGNSKAB$SB Transaktioner`" dynamic-update="true">
<id name="lbNummer">
<column name="`Løbenr`" />
<generator class="increment" />
</id>
<discriminator column="`Trans type`" />
....
When trying to save a new entry of this mapped class, I get the following failure:
2006-03-19 10:52:09,828 [main] DEBUG org.hibernate.id.IncrementGenerator - fetching initial value: select max(ids_.[Løbenr]) from ( select [Løbenr] from [Statsbiblioteket$SB union select [Løbenr] from Transaktioner] ) ids_
Hibernate: select max(ids_.[Løbenr]) from ( select [Løbenr] from [Statsbiblioteket$SB union select [Løbenr] from Transaktioner] ) ids_
2006-03-19 10:52:09,852 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 156, SQLState: S1000
2006-03-19 10:52:09,852 [main] ERROR org.hibernate.util.JDBCExceptionReporter - Incorrect syntax near the keyword 'from'.
Exception in thread "main" org.hibernate.exception.GenericJDBCException: could not fetch initial value for increment generator
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.id.IncrementGenerator.getNext(IncrementGenerator.java:107)
at org.hibernate.id.IncrementGenerator.generate(IncrementGenerator.java:44)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:90)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:186)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:175)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:27)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:534)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:522)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:518)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:301)
at $Proxy0.save(Unknown Source)
at dk.statsbiblioteket.navision.integration.UpdateItemPriceTransactionDAO.save(UpdateItemPriceTransactionDAO.java:45)
at dk.statsbiblioteket.videnstafetten.TidsskriftAar.requestNavisionItemPriceUpdate(TidsskriftAar.java:1188)
at dk.statsbiblioteket.videnstafetten.TidsskriftAar.verifyNavisionItemContents(TidsskriftAar.java:1132)
at dk.statsbiblioteket.videnstafetten.TidsskriftAar.synchronizeNavisionItem(TidsskriftAar.java:1077)
at synchronizeNavisionVare.sync(synchronizeNavisionVare.java:95)
at synchronizeNavisionVare.main(synchronizeNavisionVare.java:31)
Caused by: java.sql.SQLException: Incorrect syntax near the keyword 'from'.
at net.sourceforge.jtds.jdbc.SQLDiagnostic.addDiagnostic(SQLDiagnostic.java:365)
at net.sourceforge.jtds.jdbc.TdsCore.tdsErrorToken(TdsCore.java:2781)
at net.sourceforge.jtds.jdbc.TdsCore.nextToken(TdsCore.java:2224)
at net.sourceforge.jtds.jdbc.TdsCore.getMoreResults(TdsCore.java:628)
at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQLQuery(JtdsStatement.java:418)
at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeQuery(JtdsPreparedStatement.java:693)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeQuery(NewProxyPreparedStatement.java:76)
at org.hibernate.id.IncrementGenerator.getNext(IncrementGenerator.java:85)
... 22 more
Note that the table name contains a blank and that this causes the configure method of the generator to think that it must access two tables.
The following patch seems to fix the problem, at least for me:
svn diff
Index: IncrementGenerator.java
===================================================================
--- IncrementGenerator.java (revision 9658)
+++ IncrementGenerator.java (working copy)
@@ -51,7 +51,7 @@
String tableList = params.getProperty("tables");
if (tableList==null) tableList = params.getProperty(PersistentIdentifierGenerator.TABLES);
- String[] tables = StringHelper.split(", ", tableList);
+ String[] tables = StringHelper.split(",", tableList);
String column = params.getProperty("column");
if (column==null) column = params.getProperty(PersistentIdentifierGenerator.PK);
String schema = params.getProperty(PersistentIdentifierGenerator.SCHEMA);
What causes the problem is that StringHelper.split will tokenize the table name based on any comma and blank. My change tells it to only split on commas (as the documentation indicates).
Another approach would be to use something like
String[] tables = tableList.split(", *");
with the intention to split on a comma optionally followed by a sequence of blanks.
My patch above will still fail in the patological case of a table with a comma in its name.
The real solution might be something to really determine whether we are using quoted object names for this table and then tokenize the list of table names with respect to that.
I have seen the problem cited above with all of Hibernate 3.1, 3.1.1, 3.1.2, and 3.2.0alpha2 as well as with a home-built version based on today's svn.
Kind regards
Erik Bertelsen
|