I'm having a problem any time that I have more than a single one-to-many not-null relationship to an entity.
In this case, 'Instructor' and 'Classroom' have mandatory one-to-many relationships to 'Course'. I recently changed my mapping file to add a not-null restraint on the foreign keys in the Course table, and since doing that, Hibernate will not create a SessionFactory. I don't want to go back to the old config because it's very valuable to have a not-null constraint on the foreign keys.
My guess is that Hibernate internally creates a property called '_coursesBackref' for each mandatory relationship with 'course' as its destination, and when there are multiple relationships, it fails validation because the properties have the same name. Changing the internal name to something like '_coursesForInstructorBackref' and '_coursesForClassroomBackref' seems like it would solve it, but I'm hoping to get some help and/or confirmations of this problem before I try to start fixing the source code.
Hibernate version: 3.05
Mapping documents:
Code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.prosc.test" default-cascade="lock" default-access="field">
<class lazy="false" name="Course">
<id name="id" type="java.lang.Long" unsaved-value="null">
<generator class="native"/>
</id>
<property name="name" type="java.lang.String"/>
<property name="courseNumber" type="java.lang.String"/>
<property name="courseDescription" type="java.lang.String"/>
<many-to-one name="classroom" column="classroomId" not-null="true" update="false" insert="false"/>
<many-to-one name="instructor" column="instructorId" not-null="true" update="false" insert="false"/>
<set inverse="false" name="students" lazy="true" table="JoinCourseStudent">
<key column="coursesId"/>
<many-to-many column="studentsId" class="Student"/>
</set>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.prosc.test" default-cascade="lock" default-access="field">
<class lazy="false" name="Instructor">
<id name="id" type="java.lang.Long" unsaved-value="null">
<generator class="native"/>
</id>
<property name="firstName" type="java.lang.String"/>
<property name="lastName" type="java.lang.String"/>
<property name="title" type="java.lang.String"/>
<list name="courses" lazy="true" inverse="false">
<key column="instructorId" not-null="true"/>
<index column="sortOrderForinstructor"/>
<one-to-many class="Course"/>
</list>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.prosc.test" default-cascade="lock" default-access="field">
<class lazy="false" name="Classroom">
<id name="id" type="java.lang.Long" unsaved-value="null">
<generator class="native"/>
</id>
<property name="floor" type="java.lang.String"/>
<property name="building" type="java.lang.String"/>
<list name="courses" lazy="true" inverse="false">
<key column="classroomId" not-null="true"/>
<index column="sortOrderForclassroom"/>
<one-to-many class="Course"/>
</list>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():N/A - this happens during building the session factory. Here is the code:
Code:
Configuration config = new Configuration();
config.configure();
sessionFactory = config.buildSessionFactory();
Full stack trace of any exception that occurs:
Aug 9, 2005 12:50:49 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
java.lang.ExceptionInInitializerError
at com.prosc.test.OneToManyTest.testBadAdd(OneToManyTest.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at com.intellij.rt.execution.junit2.JUnitStarter.main(JUnitStarter.java:31)
Caused by: org.hibernate.MappingException:
duplicate property mapping: _coursesBackref
at org.hibernate.mapping.PersistentClass.checkPropertyDuplication(PersistentClass.java:344)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:334)
at org.hibernate.mapping.RootClass.validate(RootClass.java:188)
at org.hibernate.cfg.Configuration.validate(Configuration.java:839)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1000)
at com.prosc.test.TestUtils.<clinit>(TestUtils.java:33)
... 19 more
Name and version of the database you are using: MySQL 4.10
The generated SQL (show_sql=true): N/A, never gets to that point
Debug level Hibernate log excerpt: