Hello everyone,
Here's my scenario, reduced to a minimum example: I have two classes,
ClassA and
ClassB.
ClassA is a simple class mapped to a table (
<class table="CLASSA">) with a Set of
ClassB's instances. On the other hand,
ClassB is a class mapped to two tables (using
<class table="CLASSB"> and
<join table="CLASSBEXTRADATA">). The complete mapping files are shown below.
Obviously, I need a column in
ClassB's table that refers to
ClassA's ID to tie the collection. This column is named
IDCLASSA. The problem is,
IDCLASSA is
in the joined table (
CLASSBEXTRADATA), not in the main table (
CLASSB).
My mapping, as I built, makes Hibernate confused, because when I try to access the set it tries to access the
IDCLASSA in the table
CLASSB (check the "The generated SQL (show_sql=true)" section below).
This appears to be a simple matter of making the mapping files right, but I couldn't figure out how to do it.
Can anyone point me to the right direction?
Tank you very much!
----------
Hibernate version: 3.1
Mapping documents:
ClassA.hbm.xml:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="ClassA" table="CLASSA">
<id name="id" column="ID" type="int">
<generator class="assigned" />
</id>
<set name="set" lazy="false" inverse="true" cascade="none" sort="unsorted">
<key column="IDCLASSA" />
<one-to-many class="ClassB" />
</set>
</class>
</hibernate-mapping>
ClassB.hbm.xml:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="ClassB" table="CLASSB">
<id name="id" column="ID" type="int">
<generator class="assigned" />
</id>
<join table="CLASSBEXTRADATA">
<key column="ID" />
<many-to-one name="classA" class="ClassA" cascade="none" outer-join="auto" update="true" insert="true" column="IDCLASSA" />
</join>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():Anything that non-lazily loads an instance of
ClassA:
Code:
ClassA classA = (ClassA) session.get(ClassA.class, new Integer(1));
Full stack trace of any exception that occurs:Code:
org.hibernate.exception.GenericJDBCException: could not initialize a collection: [ClassA.set#1]
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:91)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:79)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.loader.Loader.loadCollection(Loader.java:1926)
at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:71)
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:520)
at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:60)
at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1627)
at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:454)
at org.hibernate.engine.StatefulPersistenceContext.initializeNonLazyCollections(StatefulPersistenceContext.java:827)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:229)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1785)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:93)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:81)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:2730)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:365)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:346)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:123)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:177)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:87)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:869)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:806)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:799)
at App.<init>(App.java:29)
at App.main(App.java:38)
Caused by: org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544569. Dynamic SQL Error
SQL error code = -206
Column unknown
SET0_.IDCLASSA
At line 1, column 192.
at org.firebirdsql.jdbc.AbstractPreparedStatement.<init>(AbstractPreparedStatement.java:118)
at org.firebirdsql.jdbc.FBPreparedStatement.<init>(FBPreparedStatement.java:40)
at org.firebirdsql.jdbc.AbstractConnection.prepareStatement(AbstractConnection.java:849)
at org.firebirdsql.jdbc.AbstractConnection.prepareStatement(AbstractConnection.java:812)
at org.firebirdsql.jdbc.AbstractConnection.prepareStatement(AbstractConnection.java:805)
at org.firebirdsql.jdbc.AbstractConnection.prepareStatement(AbstractConnection.java:286)
at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:442)
at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:368)
at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:105)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1561)
at org.hibernate.loader.Loader.doQuery(Loader.java:661)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
at org.hibernate.loader.Loader.loadCollection(Loader.java:1919)
... 21 more
The generated SQL (show_sql=true):Pretty formatted, for the sake of readability:
Code:
select set0_.IDCLASSA as IDCLASSA1_,
set0_.ID as ID1_,
set0_.ID as ID0_0_,
set0_1_.IDCLASSA as IDCLASSA1_0_
from CLASSB set0_
inner join CLASSBEXTRADATA set0_1_ on set0_.ID=set0_1_.ID
where set0_.IDCLASSA=?
(Ideally, it should be:
Code:
select set0_.ID as ID1_,
set0_.ID as ID0_0_,
set0_1_.IDCLASSA as IDCLASSA1_0_
from CLASSB set0_
inner join CLASSBEXTRADATA set0_1_ on set0_.ID=set0_1_.ID
where set0_1_.IDCLASSA=?
i.e., referring only to
CLASSBEXTRADATA.IDCLASSA, which is the actual existing column.)