I am accessing a legacy schema (ie. The schema design isn't my fault ;-) ) which has some wierd many-to-one relationships. I am only accessing this database readonly at the moment, as writing to it could get nasty.
I have a number of lookup tables of the form:
Code:
(
Code int NOT NULL ,
Version tinyint NOT NULL ,
Description varchar (255) NULL
)
Which I map with
Code:
<class name="..." table="..." mutable="false">
<composite-id name="id" class="CodeVersionId">
<key-property name="code" column="Code" />
<key-property name="version" column="Version" />
</composite-id>
<property name="description" column="Description" />
</class>
I then have another table which references these tables with a code, and a global version number:
Code:
Code1 int NULL ,
Code2 int NULL ,
Version tinyint NULL ,
I am attempting to map these like:
Code:
<property name="version" column="Version" />
<many-to-one name="code1" class="..." insert="false" update="false">
<column name="Code1" />
<column name="Version" />
</many-to-one>
<many-to-one name="code2" class="..." insert="false" update="false">
<column name="Code2" />
<column name="Version" />
</many-to-one>
My problem is that if, say Code1, is NULL, then Hibernate appears to create a CodeVersionId object with code=null, Version=<Version value>.
It then searches for this in the corresponding lookup table (InjuryAgencyCode in the attached traces) and doesn't find a matching value. Instead of setting code2 to null (my prefered behaviour in this instance.) it throws an UnresolvableObjectException and refuses to load the object.
I can work around this problem by loading the lookup objects manually, rather than relying on many-to-one relationships. I will probably need to do this anyhow if I ever want to write these values to the database. But thought I might show you this scenario in case I am missing something, or it is of interest to you.
If you require a more complete example, I can spend some time putting together a simple example that reproduces the problem.
Cheers
James
Hibernate version: 2.1.7c
Name and version of the database you are using:SQLServer 2000
Debug level Hibernate log excerpt:Code:
2005-02-16 15:53:21,289 [http-9080-Processor4] DEBUG net.sf.hibernate.impl.SessionImpl - loading [au.com.emia.claim.data.lookup.InjuryAgencyCode#CodeVersionId: code=null; version=1]
2005-02-16 15:53:21,289 [http-9080-Processor4] DEBUG net.sf.hibernate.impl.SessionImpl - attempting to resolve [au.com.emia.claim.data.lookup.InjuryAgencyCode#CodeVersionId: code=null; version=1]
2005-02-16 15:53:21,289 [http-9080-Processor4] DEBUG net.sf.hibernate.impl.SessionImpl - object not resolved in any cache [au.com.emia.claim.data.lookup.InjuryAgencyCode#CodeVersionId: code=null; version=1]
2005-02-16 15:53:21,289 [http-9080-Processor4] DEBUG net.sf.hibernate.persister.EntityPersister - Materializing entity: [au.com.emia.claim.data.lookup.InjuryAgencyCode#CodeVersionId: code=null; version=1]
2005-02-16 15:53:21,289 [http-9080-Processor4] DEBUG net.sf.hibernate.impl.BatcherImpl - about to open: 0 open PreparedStatements, 0 open ResultSets
2005-02-16 15:53:21,289 [http-9080-Processor4] DEBUG net.sf.hibernate.SQL - select injuryagen0_.Code as Code0_, injuryagen0_.version as version0_, injuryagen0_.Description as Descript3_0_ from AGENCY_DESC injuryagen0_ where injuryagen0_.Code=? and injuryagen0_.version=?
2005-02-16 15:53:21,289 [http-9080-Processor4] DEBUG net.sf.hibernate.impl.BatcherImpl - preparing statement
2005-02-16 15:53:21,289 [http-9080-Processor4] DEBUG net.sf.hibernate.type.IntegerType - binding null to parameter: 1
2005-02-16 15:53:21,289 [http-9080-Processor4] DEBUG net.sf.hibernate.type.IntegerType - binding '1' to parameter: 2
2005-02-16 15:53:21,305 [http-9080-Processor4] DEBUG net.sf.hibernate.loader.Loader - processing result set
2005-02-16 15:53:21,305 [http-9080-Processor4] DEBUG net.sf.hibernate.loader.Loader - done processing result set (0 rows)
Full stack trace of any exception that occurs:Code:
org.springframework.orm.hibernate.HibernateObjectRetrievalFailureException: No row with the given identifier exists: CodeVersionId: code=null; version=1, of class: au.com.emia.claim.data.lookup.InjuryAgencyCode; nested exception is net.sf.hibernate.UnresolvableObjectException: No row with the given identifier exists: CodeVersionId: code=null; version=1, of class: au.com.emia.claim.data.lookup.InjuryAgencyCode
net.sf.hibernate.UnresolvableObjectException: No row with the given identifier exists: CodeVersionId: code=null; version=1, of class: au.com.emia.claim.data.lookup.InjuryAgencyCode
at net.sf.hibernate.UnresolvableObjectException.throwIfNull(UnresolvableObjectException.java:38)
at net.sf.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:1963)
at net.sf.hibernate.type.ManyToOneType.resolveIdentifier(ManyToOneType.java:69)
at net.sf.hibernate.type.EntityType.resolveIdentifier(EntityType.java:204)
at net.sf.hibernate.impl.SessionImpl.initializeEntity(SessionImpl.java:2218)
at net.sf.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:315)
at net.sf.hibernate.loader.Loader.doQuery(Loader.java:305)
at net.sf.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:133)
at net.sf.hibernate.loader.Loader.doList(Loader.java:1033)
at net.sf.hibernate.loader.Loader.list(Loader.java:1024)
at net.sf.hibernate.hql.QueryTranslator.list(QueryTranslator.java:854)
at net.sf.hibernate.impl.SessionImpl.find(SessionImpl.java:1553)
at net.sf.hibernate.impl.QueryImpl.list(QueryImpl.java:39)
at org.springframework.orm.hibernate.HibernateTemplate$37.doInHibernate(HibernateTemplate.java:675)
at org.springframework.orm.hibernate.HibernateTemplate.execute(HibernateTemplate.java:200)
at org.springframework.orm.hibernate.HibernateTemplate.executeFind(HibernateTemplate.java:220)
at org.springframework.orm.hibernate.HibernateTemplate.findByNamedQueryAndNamedParam(HibernateTemplate.java:671)
at au.com.emia.claim.ClaimHibernateDb.findClaim(ClaimHibernateDb.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.springframework.aop.framework.AopProxyUtils.invokeJoinpointUsingReflection(AopProxyUtils.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:149)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:116)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:56)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:138)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:152)
at $Proxy2.findClaim(Unknown Source)
at au.com.emia.claim.ClaimProcessorImpl.findClaim(ClaimProcessorImpl.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.springframework.aop.framework.AopProxyUtils.invokeJoinpointUsingReflection(AopProxyUtils.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:149)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:116)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:56)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:138)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:152)
at $Proxy4.findClaim(Unknown Source)
at au.com.emia.claim.web.SearchFormController.onSubmit(SearchFormController.java:62)
at org.springframework.web.servlet.mvc.SimpleFormController.processFormSubmission(SimpleFormController.java:223)
at org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:237)
at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:128)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:44)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:522)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:321)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:809)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:200)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:146)
at au.com.emia.member.security.web.SecurityContextInitialiser.doFilterInternal(SecurityContextInitialiser.java:71)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:73)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:146)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:209)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:596)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:433)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:948)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:144)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:596)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:433)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:948)
at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2358)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:133)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:596)
at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:118)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:594)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:116)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:594)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:433)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:948)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:127)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:596)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:433)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:948)
at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:152)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:799)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:705)
at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:577)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)
at java.lang.Thread.run(Thread.java:534)