Joined: Mon Jun 25, 2007 3:43 am Posts: 1
|
Background:
Our application uses a "subclass-per-table"-hierarchy. The superclass, called LogRecords, holds a discriminator column. The application consists of two, standalone, parts: one which logs data to the database and one which reads data from the database. The reading part may use a different version of the mapping files than the logging part.
For example, the logging part uses version 3 of the mapping files containing subclasses "a","b" and "c" whereas the reading part uses version 2 of the mapping files which only contains definitions of subclasses "a" and "b".
Problem:
We recently added a formula attribute in the discriminator tag in order to make the "reading" part of the application able to handle subclasses that had no definition in its mapping file. Previously, Hibernate would throw an exception if it found subclass "c" which was not defined in the mapping files. This behaviour is natural, so we introduced a formula attribute in the discriminator part that states that if the subclass belongs to a set of "unknown" subclasses, then treat it as a superclass:
<hibernate-mapping package="se.micronic.milou.model"> <class table="logrecords" discriminator-value="0" name="LogRecord" node="logrecord"> <id column="logrecord_id" name="logRecordId" node="@id"></id> <discriminator column="subclass_table" formula="case when subclass_table in ('1','2','3') then '0' else subclass_table end"/> ...
This works fine when using selects. However, when using inserts, Hibernate generates an unexpected JDBC insert: it simply excludes the discriminator column from the insert, which generates an JDBC exception: 2007-06-25 00:17:54.671 DEBUG org.hibernate.SQL log select logrecord0_.logrecord_id as logrecord1_15_0_, logrecord0_.dbtime as dbtime15_0_, logrecord0_.parentlogrecord_id as parentlo3_15_0_, logrecord0_.logrecordtype_id as logrecor4_15_0_, logrecord0_.logtime as logtime15_0_, case when logrecord0_.subclass_table in ('1','2','3') then '0' else logrecord0_.subclass_table end as clazz_0_ from logrecords logrecord0_ where logrecord0_.logrecord_id=?
// The insert does not contain the subclass_table column, which leads to the error below 2007-06-25 00:17:54.686 DEBUG org.hibernate.SQL log insert into logrecords (dbtime, parentlogrecord_id, logrecordtype_id, logtime, logrecord_id) values (?, ?, ?, ?, ?)
2007-06-25 00:17:54.733 WARN org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 1364, SQLState: HY000 2007-06-25 00:17:54.733 ERROR org.hibernate.util.JDBCExceptionReporter logExceptions Field 'subclass_table' doesn't have a default value
The same scenario without the formula attribute generates a correct insert statement which works fine:2007-06-25 00:07:00.773 DEBUG org.hibernate.SQL log select logrecord0_.logrecord_id as logrecord1_1_0_, logrecord0_.dbtime as dbtime1_0_, logrecord0_.parentlogrecord_id as parentlo4_1_0_, logrecord0_.logrecordtype_id as logrecor5_1_0_, logrecord0_.logtime as logtime1_0_, logrecord0_.subclass_table as subclass2_1_0_ from logrecords logrecord0_ where logrecord0_.logrecord_id=?
// Note that the subclass_table column is present 2007-06-25 00:07:00.804 DEBUG org.hibernate.SQL log insert into logrecords (dbtime, parentlogrecord_id, logrecordtype_id, logtime, subclass_table, logrecord_id) values (?, ?, ?, ?, '60501', ?)
We don't understand why the formula attribute in the discriminator tag makes Hibernate behave this way. Should we have defined the formula in a different way, or is there any other workaround? We would be grateful for any help. Hibernate version: 3.2.2.raMapping documents:<hibernate-mapping package="se.micronic.milou.model"> <class table="logrecords" discriminator-value="0" name="LogRecord" node="logrecord"> <id column="logrecord_id" name="logRecordId" node="@id"> </id> <discriminator column="subclass_table" formula="case when subclass_table in ('1','2','3','64601','64602','64603','64701','64702','64703','64801','64802','64803','64901','64902','64903','65001','65002','65003','65101','65102','65103','65201','65202','65203','65301','65302','65303','65401','65402','65403','65501','65502','65503','65601','65602','65603','65701','65702','65703','65801','65802','65803','65901','65902','65903','66001','66002','66003','66101','66102','66103','66500','66201','66202','66203','66301','66302','66303','66401','66402','66403') then '0' else subclass_table end"/> <timestamp name="dbtime" node="dbtime"/> <many-to-one class="LogRecord" column="parentlogrecord_id" name="parentLogrecord" node="parentlogrecord"/> <many-to-one class="LogRecordType" column="logrecordtype_id" name="logRecordType" lazy="false" fetch="select" node="logrecordtype"/> <property not-null="true" name="logtime" node="logtime"/> <set cascade="all" name="userComments" lazy="true"> <key column="logrecord_id"/> <one-to-many class="Comment"/> </set> </class> <subclass extends="se.micronic.milou.model.LogRecord" discriminator-value="1" name="LogRecordRootStartAct"> <join fetch="select" table="rootstartact"> <key column="logrecord_id"/> <property name="name" column="_name"/> </join> </subclass> <subclass extends="se.micronic.milou.model.LogRecord" discriminator-value="2" name="LogRecordRootEndActOk"> <join fetch="select" table="rootendactok"> <key column="logrecord_id"/> </join> </subclass> <subclass extends="se.micronic.milou.model.LogRecord" discriminator-value="3" name="LogRecordRootEndActFail"> <join fetch="select" table="endactfail"> <key column="logrecord_id"/> </join> </subclass> </hibernate-mapping>
Full stack trace of any exception that occurs:2007-06-25 08:45:06.752 DEBUG org.hibernate.SQL log select logrecord0_.logrecord_id as logrecord1_1_0_, logrecord0_.dbtime as dbtime1_0_, logrecord0_.parentlogrecord_id as parentlo3_1_0_, logrecord0_.logrecordtype_id as logrecor4_1_0_, logrecord0_.logtime as logtime1_0_, case when logrecord0_.subclass_table in ('1','2','3','64601','64602','64603','64701','64702','64703','64801','64802','64803','64901','64902','64903','65001','65002','65003','65101','65102','65103','65201','65202','65203','65301','65302','65303','65401','65402','65403','65501','65502','65503','65601','65602','65603','65701','65702','65703','65801','65802','65803','65901','65902','65903','66001','66002','66003','66101','66102','66103','66500','66201','66202','66203','66301','66302','66303','66401','66402','66403') then '0' else logrecord0_.subclass_table end as clazz_0_ from logrecords logrecord0_ where logrecord0_.logrecord_id=?
2007-06-25 08:45:06.767 DEBUG org.hibernate.SQL log insert into logrecords (dbtime, parentlogrecord_id, logrecordtype_id, logtime, logrecord_id) values (?, ?, ?, ?, ?)
2007-06-25 08:45:06.814 WARN org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 1364, SQLState: HY000
2007-06-25 08:45:06.830 ERROR org.hibernate.util.JDBCExceptionReporter logExceptions Field 'subclass_table' doesn't have a default value
2007-06-25 08:45:06.845 ERROR org.hibernate.event.def.AbstractFlushingEventListener performExecutions Could not synchronize database state with sessionorg.hibernate.exception.GenericJDBCException Could not execute JDBC batch update org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
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.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:249)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:92)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:87)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2228)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2656)
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:52)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:139)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at se.micronic.milou.gui.dataaccess.hibernate.LogRecordManipulationDao$1.onEnd(LogRecordManipulationDao.java:309)
at org.dom4j.io.DispatchHandler.onEnd(DispatchHandler.java:202)
at org.dom4j.io.SAXContentHandler.endElement(SAXContentHandler.java:268)
at org.apache.xerces.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:579)
at org.apache.xerces.impl.XMLNamespaceBinder.handleEndElement(XMLNamespaceBinder.java:897)
at org.apache.xerces.impl.XMLNamespaceBinder.endElement(XMLNamespaceBinder.java:643)
at org.apache.xerces.impl.dtd.XMLDTDValidator.handleEndElement(XMLDTDValidator.java:1972)
at org.apache.xerces.impl.dtd.XMLDTDValidator.endElement(XMLDTDValidator.java:878)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.handleEndElement(XMLDocumentFragmentScannerImpl.java:1144)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:987)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(XMLDocumentFragmentScannerImpl.java:1445)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:333)
at org.apache.xerces.parsers.DTDConfiguration.parse(DTDConfiguration.java:524)
at org.apache.xerces.parsers.DTDConfiguration.parse(DTDConfiguration.java:580)
at org.apache.xerces.parsers.XMLParser.parse(XMLParser.java:152)
at org.apache.xerces.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1169)
at org.dom4j.io.SAXReader.read(SAXReader.java:465)
at org.dom4j.io.SAXReader.read(SAXReader.java:365)
at se.micronic.milou.gui.dataaccess.hibernate.LogRecordManipulationDao.parseXmlDoc(LogRecordManipulationDao.java:343)
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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:292)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:163)
at $Proxy4.parseXmlDoc(Unknown Source)
at se.micronic.milou.gui.web.beans.AdministrationProvider.importFiles(AdministrationProvider.java:121)
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.apache.myfaces.el.MethodBindingImpl.invoke(MethodBindingImpl.java:129)
at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:63)
at javax.faces.component.UICommand.broadcast(UICommand.java:106)
at javax.faces.component.UIViewRoot._broadcastForPhase(UIViewRoot.java:94)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:168)
at org.apache.myfaces.lifecycle.LifecycleImpl.invokeApplication(LifecycleImpl.java:343)
at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:86)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:137)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:144)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at se.micronic.milou.gui.web.security.NewSecurityFilter.doFilter(NewSecurityFilter.java:49)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
at java.lang.Thread.run(Unknown Source)
Caused by: java.sql.BatchUpdateException: Field 'subclass_table' doesn't have a default value
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1213)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:912)
at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:205)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:242)
... 72 more
Name and version of the database you are using:MySql 5.0 MySql 5.0mysql-connector (jdbc-driver) 5.0.5 The generated SQL (show_sql=true):2007-06-25 11:15:27.136 DEBUG org.hibernate.SQL log select logrecord0_.logrecord_id as logrecord1_1_0_, logrecord0_.dbtime as dbtime1_0_, logrecord0_.parentlogrecord_id as parentlo3_1_0_, logrecord0_.logrecordtype_id as logrecor4_1_0_, logrecord0_.logtime as logtime1_0_, case when logrecord0_.subclass_table in ('1','2','3','64601','64602','64603','64701','64702','64703','64801','64802','64803','64901','64902','64903','65001','65002','65003','65101','65102','65103','65201','65202','65203','65301','65302','65303','65401','65402','65403','65501','65502','65503','65601','65602','65603','65701','65702','65703','65801','65802','65803','65901','65902','65903','66001','66002','66003','66101','66102','66103','66500','66201','66202','66203','66301','66302','66303','66401','66402','66403') then '0' else logrecord0_.subclass_table end as clazz_0_ from logrecords logrecord0_ where logrecord0_.logrecord_id=?
2007-06-25 11:15:27.136 DEBUG org.hibernate.type.LongType nullSafeSet binding '1495001' to parameter: 1
2007-06-25 11:15:27.152 DEBUG org.hibernate.type.StringType nullSafeGet returning '46601' as column: clazz_0_
2007-06-25 11:15:27.152 DEBUG org.hibernate.type.TimestampType nullSafeGet returning '2007-03-21 15:15:46' as column: dbtime1_0_
2007-06-25 11:15:27.152 DEBUG org.hibernate.type.LongType nullSafeGet returning null as column: parentlo3_1_0_
2007-06-25 11:15:27.152 DEBUG org.hibernate.type.IntegerType nullSafeGet returning '46601' as column: logrecor4_1_0_
2007-06-25 11:15:27.152 DEBUG org.hibernate.type.LongType nullSafeGet returning '1174486508335' as column: logtime1_0_
2007-06-25 11:15:27.167 DEBUG org.hibernate.SQL log insert into logrecords (dbtime, parentlogrecord_id, logrecordtype_id, logtime, logrecord_id) values (?, ?, ?, ?, ?)
2007-06-25 11:15:27.167 DEBUG org.hibernate.type.TimestampType nullSafeSet binding '2007-06-25 11:15:27' to parameter: 1
2007-06-25 11:15:27.167 DEBUG org.hibernate.type.LongType nullSafeSet binding '1495001' to parameter: 2
2007-06-25 11:15:27.183 DEBUG org.hibernate.type.IntegerType nullSafeSet binding '60501' to parameter: 3
2007-06-25 11:15:27.183 DEBUG org.hibernate.type.LongType nullSafeSet binding '1174486691597' to parameter: 4
2007-06-25 11:15:27.183 DEBUG org.hibernate.type.LongType nullSafeSet binding '1495620' to parameter: 5
2007-06-25 11:15:27.246 WARN org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 1364, SQLState: HY000
2007-06-25 11:15:27.246 ERROR org.hibernate.util.JDBCExceptionReporter logExceptions Field 'subclass_table' doesn't have a default value
|
|