Hibernate version: 3.1
All the mapping files, code, logs, etc. are below. I am getting a ClassCastException when calling merge() on an object (Station) that has a dependent object (StationState) with a one-to-one foreign key.
Here are my tables (generated by Hibernate Tools from mapping files, along with my POJOs):
Code:
create table nathan.station (station_id int8 not null unique, primary key (station_id));
create table nathan.stationstate (stationstate_id int8 not null unique, station_id int8 not null, primary key (stationstate_id));
Data in the tables looks like:
station table:
Code:
station_id
-----------
1
stationstate table:
Code:
stationstate_id | station_id
--------------- | -----------
2 | 1
I load a Station object, clear the session, then call merge() to re-associate the Station with the session. You can see from the logs that the first time I load the object, it correctly loads the StationState along with the Station (using left outer join). On the merge, however, it loads first the Station, then tries to resolve associations. It loads the StationState ok, but it seems that it mistakenly thinks that station_id is the PK of stationstate (it prints out loader.Loader - loading entity: [com.nathan.hibernatetest.StationState#1] which I think is saying it thinks that station_id (1) is the PK of stationstate instead of stationstate_id (2)).
Then it tries to load StationState again, but using the Station object as the PK, causing a ClassCastException! Is my mapping file wrong, causing Hibernate to believe that the stationstate table is a PK/FK one-to-one instead of just a FK one-to-one?
How do I fix my Station mapping file so that Hibernate knows that StationState has its own PK?? I followed the docs in creating the association.
Thanks in advance for any help.
Mapping documents:Code:
<class
name="Station"
table="station"
schema="nathan">
<id
name="StationId"
type="java.lang.Long">
<column
name="station_id"
not-null="true"
unique="true" />
<generator class="native" />
</id>
<one-to-one
name="StationState"
class="StationState"
property-ref="Station" />
</class>
Code:
<class
name="StationState"
table="stationstate"
schema="nathan">
<id
name="StationStateId"
type="java.lang.Long">
<column
name="stationstate_id"
not-null="true"
unique="true" />
<generator class="native" />
</id>
<many-to-one
name="Station"
class="Station"
unique="true">
<column
name="station_id"
not-null="true" />
</many-to-one>
</class>
Code between sessionFactory.openSession() and session.close():Code:
Session s = sf.openSession();
Transaction t = s.beginTransaction();
Station station = (Station)s.get(Station.class, new Long(1));
s.clear();
try {
s.merge(station);
} catch (Exception e) {
throw e;
}
t.commit();
s.close();
Full stack trace of any exception that occurs:Quote:
java.lang.ClassCastException
at org.hibernate.type.LongType.set(LongType.java:42)
at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:63)
at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:45)
at org.hibernate.loader.Loader.bindPositionalParameters(Loader.java:1514)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1576)
at org.hibernate.loader.Loader.doQuery(Loader.java:661)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:223)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1782)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:47)
at org.hibernate.loader.entity.EntityLoader.loadByUniqueKey(EntityLoader.java:85)
at org.hibernate.persister.entity.AbstractEntityPersister.loadByUniqueKey(AbstractEntityPersister.java:1512)
at org.hibernate.type.EntityType.loadByUniqueKey(EntityType.java:365)
at org.hibernate.type.EntityType.resolve(EntityType.java:306)
at org.hibernate.type.EntityType.replace(EntityType.java:207)
at org.hibernate.type.TypeFactory.replace(TypeFactory.java:431)
at org.hibernate.event.def.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:279)
at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:245)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:102)
at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:53)
at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:608)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:594)
at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:598)
at StationTest.testOne(StationTest.java:110)
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 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:478)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Name and version of the database you are using:PostgreSQL 8
The generated SQL (show_sql=true):(See DEBUG Hibernate log:)
Debug level Hibernate log excerpt:Quote:
3890 DEBUG [main] impl.SessionImpl - opened session at timestamp: 4620662712664064
3890 DEBUG [main] transaction.JDBCTransaction - begin
3890 DEBUG [main] jdbc.ConnectionManager - opening JDBC connection
3890 DEBUG [main] transaction.JDBCTransaction - current autocommit status: false
3890 DEBUG [main] jdbc.JDBCContext - before transaction completion
3906 DEBUG [main] def.DefaultLoadEventListener - loading entity: [com.nathan.hibernatetest.Station#1]
3906 DEBUG [main] def.DefaultLoadEventListener - attempting to resolve: [com.nathan.hibernatetest.Station#1]
3906 DEBUG [main] def.DefaultLoadEventListener - object not resolved in any cache: [com.nathan.hibernatetest.Station#1]
3906 DEBUG [main] entity.AbstractEntityPersister - Fetching entity: [com.nathan.hibernatetest.Station#1]
3906 DEBUG [main] loader.Loader - loading entity: [com.nathan.hibernatetest.Station#1]
3921 DEBUG [main] jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
3921 DEBUG [main] hibernate.SQL - select station0_.station_id as station1_22_1_, stationsta1_.stationstate_id as stations1_23_0_, stationsta1_.station_id as station2_23_0_ from nathan.station station0_ left outer join nathan.stationstate stationsta1_ on station0_.station_id=stationsta1_.station_id where station0_.station_id=?
3921 DEBUG [main] jdbc.AbstractBatcher - preparing statement
3937 DEBUG [main] type.LongType - binding '1' to parameter: 1
3968 DEBUG [main] jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 0, globally: 0)
3968 DEBUG [main] loader.Loader - processing result set
3968 DEBUG [main] loader.Loader - result set row: 0
3968 DEBUG [main] type.LongType - returning '2' as column: stations1_23_0_
3968 DEBUG [main] loader.Loader - result row: EntityKey[com.nathan.hibernatetest.StationState#2], EntityKey[com.nathan.hibernatetest.Station#1]
3968 DEBUG [main] loader.Loader - Initializing object from ResultSet: [com.nathan.hibernatetest.StationState#2]
3984 DEBUG [main] entity.AbstractEntityPersister - Hydrating entity: [com.nathan.hibernatetest.StationState#2]
3984 DEBUG [main] type.LongType - returning '1' as column: station2_23_0_
3999 DEBUG [main] loader.Loader - Initializing object from ResultSet: [com.nathan.hibernatetest.Station#1]
3999 DEBUG [main] entity.AbstractEntityPersister - Hydrating entity: [com.nathan.hibernatetest.Station#1]
3999 DEBUG [main] loader.Loader - done processing result set (1 rows)
3999 DEBUG [main] jdbc.AbstractBatcher - about to close ResultSet (open ResultSets: 1, globally: 1)
3999 DEBUG [main] jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
3999 DEBUG [main] jdbc.AbstractBatcher - closing statement
4015 DEBUG [main] loader.Loader - total objects hydrated: 2
4015 DEBUG [main] engine.TwoPhaseLoad - resolving associations for [com.nathan.hibernatetest.StationState#2]
4015 DEBUG [main] def.DefaultLoadEventListener - loading entity: [com.nathan.hibernatetest.Station#1]
4015 DEBUG [main] def.DefaultLoadEventListener - entity found in session cache
4015 DEBUG [main] engine.TwoPhaseLoad - done materializing entity [com.nathan.hibernatetest.StationState#2]
4015 DEBUG [main] engine.TwoPhaseLoad - resolving associations for [com.nathan.hibernatetest.Station#1]
4015 DEBUG [main] engine.TwoPhaseLoad - done materializing entity [com.nathan.hibernatetest.Station#1]
4015 DEBUG [main] engine.StatefulPersistenceContext - initializing non-lazy collections
4015 DEBUG [main] loader.Loader - done entity load
4031 DEBUG [main] engine.IdentifierValue - id unsaved-value: null
4031 DEBUG [main] def.AbstractSaveEventListener - detached instance of: com.nathan.hibernatetest.Station
4031 DEBUG [main] def.DefaultMergeEventListener - merging detached instance
4031 DEBUG [main] def.DefaultLoadEventListener - loading entity: [com.nathan.hibernatetest.Station#1]
4031 DEBUG [main] def.DefaultLoadEventListener - attempting to resolve: [com.nathan.hibernatetest.Station#1]
4031 DEBUG [main] def.DefaultLoadEventListener - object not resolved in any cache: [com.nathan.hibernatetest.Station#1]
4031 DEBUG [main] entity.AbstractEntityPersister - Fetching entity: [com.nathan.hibernatetest.Station#1]
4031 DEBUG [main] loader.Loader - loading entity: [com.nathan.hibernatetest.Station#1]
4031 DEBUG [main] jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
4031 DEBUG [main] hibernate.SQL - select station0_.station_id as station1_22_0_ from nathan.station station0_ where station0_.station_id=?
4031 DEBUG [main] jdbc.AbstractBatcher - preparing statement
4031 DEBUG [main] type.LongType - binding '1' to parameter: 1
4031 DEBUG [main] jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 0, globally: 0)
4031 DEBUG [main] loader.Loader - processing result set
4031 DEBUG [main] loader.Loader - result set row: 0
4031 DEBUG [main] loader.Loader - result row: EntityKey[com.nathan.hibernatetest.Station#1]
4031 DEBUG [main] loader.Loader - Initializing object from ResultSet: [com.nathan.hibernatetest.Station#1]
4031 DEBUG [main] entity.AbstractEntityPersister - Hydrating entity: [com.nathan.hibernatetest.Station#1]
4031 DEBUG [main] loader.Loader - done processing result set (1 rows)
4031 DEBUG [main] jdbc.AbstractBatcher - about to close ResultSet (open ResultSets: 1, globally: 1)
4031 DEBUG [main] jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
4031 DEBUG [main] jdbc.AbstractBatcher - closing statement
4031 DEBUG [main] loader.Loader - total objects hydrated: 1
4031 DEBUG [main] engine.TwoPhaseLoad - resolving associations for [com.nathan.hibernatetest.Station#1]
4031 DEBUG [main] loader.Loader - loading entity: [com.nathan.hibernatetest.StationState#1]
4031 DEBUG [main] jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
4031 DEBUG [main] hibernate.SQL - select stationsta0_.stationstate_id as stations1_23_0_, stationsta0_.station_id as station2_23_0_ from nathan.stationstate stationsta0_ where stationsta0_.station_id=?
4031 DEBUG [main] jdbc.AbstractBatcher - preparing statement
4031 DEBUG [main] type.LongType - binding '1' to parameter: 1
4031 DEBUG [main] jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 0, globally: 0)
4031 DEBUG [main] loader.Loader - processing result set
4031 DEBUG [main] loader.Loader - result set row: 0
4046 DEBUG [main] type.LongType - returning '2' as column: stations1_23_0_
4046 DEBUG [main] loader.Loader - result row: EntityKey[com.nathan.hibernatetest.StationState#2]
4046 DEBUG [main] loader.Loader - Initializing object from ResultSet: [com.nathan.hibernatetest.StationState#2]
4046 DEBUG [main] entity.AbstractEntityPersister - Hydrating entity: [com.nathan.hibernatetest.StationState#2]
4046 DEBUG [main] type.LongType - returning '1' as column: station2_23_0_
4046 DEBUG [main] loader.Loader - done processing result set (1 rows)
4046 DEBUG [main] jdbc.AbstractBatcher - about to close ResultSet (open ResultSets: 1, globally: 1)
4046 DEBUG [main] jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
4046 DEBUG [main] jdbc.AbstractBatcher - closing statement
4046 DEBUG [main] loader.Loader - total objects hydrated: 1
4046 DEBUG [main] engine.TwoPhaseLoad - resolving associations for [com.nathan.hibernatetest.StationState#2]
4046 DEBUG [main] def.DefaultLoadEventListener - loading entity: [com.nathan.hibernatetest.Station#1]
4046 DEBUG [main] def.DefaultLoadEventListener - entity found in session cache
4046 DEBUG [main] engine.TwoPhaseLoad - done materializing entity [com.nathan.hibernatetest.StationState#2]
4046 DEBUG [main] loader.Loader - done entity load
4046 DEBUG [main] engine.TwoPhaseLoad - done materializing entity [com.nathan.hibernatetest.Station#1]
4046 DEBUG [main] engine.StatefulPersistenceContext - initializing non-lazy collections
4046 DEBUG [main] loader.Loader - done entity load
4046 DEBUG [main] loader.Loader - loading entity: [com.nathan.hibernatetest.StationState#com.nathan.hibernatetest.Station@691dee]
4046 DEBUG [main] jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
4046 DEBUG [main] hibernate.SQL - select stationsta0_.stationstate_id as stations1_23_0_, stationsta0_.station_id as station2_23_0_ from nathan.stationstate stationsta0_ where stationsta0_.station_id=?
4046 DEBUG [main] jdbc.AbstractBatcher - preparing statement
4046 DEBUG [main] type.LongType - binding 'com.nathan.hibernatetest.Station@691dee' to parameter: 1
[/code]