Issue:
I have 2 many-to-one associations, both using composite keys.
The composite keys both share collumn 'b', which is also part of composite primary key.
The Hibernate session fails to load unless I add attributes: update="false" insert="false" to the mapping.
However if I add these attributes to the mapping I can no longer save new persistent instances, because hibernate attempts to leave 'not null' fields empty.
Is there a solution to this other than adding redundant columns as copies of column 'b' to use uniquely in each association ?
I do have very good reasons for wishing to use composite primary keys - it helps massively with both query efficiency and data integrity
Hibernate version: 2.1.4
Mapping documents:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<hibernate-mapping>
<!--
Created by the Middlegen Hibernate plugin 2.1
http://boss.bekk.no/boss/middlegen/
http://www.hibernate.org/
-->
<class
name="aa.bb.cc.dd.head"
table="head"
>
<composite-id name="comp_id" class="aa.bb.cc.dd.headPK">
<meta attribute="field-description" inherit="false">
@hibernate.id
generator-class="assigned"
</meta>
<key-property
name="a"
column="a"
type="java.lang.Integer"
length="4"
>
</key-property>
<key-property
name="b"
column="b"
type="java.lang.Integer"
length="4"
>
</key-property>
</composite-id>
<!-- Associations -->
<!-- bi-directional many-to-one association to nose-->
<many-to-one
name="nose"
class="name="aa.bb.cc.dd.nose"
not-null="true"
>
<meta attribute="field-description">
@hibernate.many-to-one
not-null="true"
@hibernate.column name="b"
@hibernate.column name="x"
</meta>
<column name="depot_code" />
<column name="ho"/>
</many-to-one>
<!-- bi-directional many-to-one association to mouth-->
<many-to-one
name="mouth"
class="aa.bb.cc.dd.mouth"
not-null="true"
>
<meta attribute="field-description">
@hibernate.many-to-one
not-null="true"
@hibernate.column name="b"
@hibernate.column name="y"
</meta>
<column name="ho" />
<column name="ho_brand_code" />
</many-to-one>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():
Full stack trace of any exception that occurs:
junit.framework.AssertionFailedError: failed to get hibernate session
net.sf.hibernate.MappingException: Repeated column in mapping for class aa.bb.cc.dd.head should be mapped with insert="false" update="false": b
at net.sf.hibernate.persister.AbstractEntityPersister.checkColumnDuplication(AbstractEntityPersister.java:1002)
at net.sf.hibernate.persister.EntityPersister.<init>(EntityPersister.java:821)
at net.sf.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:42)
at net.sf.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:137)
at net.sf.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:768)
at net.inspiredbroadcast.legion.common.hibernate.HibernateSessionUtil.currentSession(HibernateSessionUtil.java:45)
at net.inspiredbroadcast.legion.configdb.entity.FunctionalBusinessTest.test001DbVersion(FunctionalBusinessTest.java:49)
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 junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:421)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:305)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:186)
at junit.framework.Assert.fail(Assert.java:47)
at net.inspiredbroadcast.legion.configdb.entity.FunctionalBusinessTest.failTest(FunctionalBusinessTest.java:513)
at net.inspiredbroadcast.legion.configdb.entity.FunctionalBusinessTest.test001DbVersion(FunctionalBusinessTest.java:51)
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 junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:421)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:305)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:186)