I took the "23.4.5. Associations on alternate keys" example and made both Person and Account have composite keys. My example works, but Hibernate will throw a ClassCastException ONLY if debug logging is turned on.
Hibernate version: 3.2 CR2
Mapping documents:
Code:
<class name="test2.Person">
<composite-id>
<key-property name="id1" length="100"/>
<key-property name="id2" length="100"/>
</composite-id>
<property name="name" length="100"/>
<set name="accounts"
inverse="true">
<key column="userId"
property-ref="userId"/>
<one-to-many class="test2.Account"/>
</set>
<property name="userId" length="8"/>
</class>
<class name="test2.Account">
<composite-id>
<key-property name="id1" length="100"/>
<key-property name="id2" length="100"/>
</composite-id>
<many-to-one name="user"
column="userId"
property-ref="userId"/>
<property name="type" not-null="true"/>
</class>
Code between sessionFactory.openSession() and session.close():Code:
Person p = new Person();
p.setId1("a1");
p.setId2("a2");
p.setUserId("user1");
p.setName("username1");
Account a = new Account();
a.setId1("a1");
a.setId2("a2");
a.setUser(p);
a.setType("type");
Set accounts = new HashSet();
accounts.add(a);
p.setAccounts(accounts);
sess.save(p);
sess.save(a);
sess.flush();
Query q = sess.createQuery("from Person p join fetch p.accounts");
List l = q.list();
Full stack trace of any exception that occurs:This occurs on the flush() call and only if debug logging is on
Code:
java.lang.ClassCastException: java.lang.String
at org.hibernate.type.ComponentType.toLoggableString(ComponentType.java:329)
at org.hibernate.pretty.MessageHelper.collectionInfoString(MessageHelper.java:284)
at org.hibernate.engine.Collections.processReachableCollection(Collections.java:176)
at org.hibernate.event.def.FlushVisitor.processCollection(FlushVisitor.java:37)
at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:101)
at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:61)
at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:55)
at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:131)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:195)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:76)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:993)
at test2.AltKeyJoinWithCompKeysTest.testAnything(AltKeyJoinWithCompKeysTest.java:127)
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:585)
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: hsql 1.8.0
The generated SQL (show_sql=true): None
Debug level Hibernate log excerpt:Everything after the schema export:
Code:
10:29:08,513 DEBUG [DriverManagerConnectionProvider] returning connection to pool, pool size: 1
10:29:08,513 DEBUG [Configuration] processing extends queue
10:29:08,513 DEBUG [Configuration] processing collection mappings
10:29:08,513 DEBUG [Configuration] processing native query and ResultSetMapping mappings
10:29:08,513 DEBUG [Configuration] processing association property references
10:29:08,513 DEBUG [Configuration] processing foreign key constraints
10:29:08,513 DEBUG [Configuration] resolving reference to class: test2.Person
10:29:08,513 DEBUG [Configuration] processing extends queue
10:29:08,513 DEBUG [Configuration] processing collection mappings
10:29:08,513 DEBUG [Configuration] processing native query and ResultSetMapping mappings
10:29:08,513 DEBUG [Configuration] processing association property references
10:29:08,513 DEBUG [Configuration] processing foreign key constraints
10:29:08,513 DEBUG [Configuration] resolving reference to class: test2.Person
10:29:08,513 DEBUG [SessionFactoryImpl] Checking 0 named HQL queries
10:29:08,513 DEBUG [SessionFactoryImpl] Checking 0 named SQL queries
10:29:08,591 DEBUG [SessionImpl] opened session at timestamp: 4726119417909248
10:29:08,622 DEBUG [ConnectionManager] opening JDBC connection
10:29:08,622 DEBUG [DriverManagerConnectionProvider] total checked-out connections: 0
10:29:08,622 DEBUG [DriverManagerConnectionProvider] using pooled JDBC connection, pool size: 0
10:29:08,638 DEBUG [DefaultSaveOrUpdateEventListener] saving transient instance
10:29:08,638 DEBUG [AbstractSaveEventListener] generated identifier: component[id1,id2]{id1=a1, id2=a2}, using strategy: org.hibernate.id.Assigned
10:29:08,638 DEBUG [AbstractSaveEventListener] saving [test2.Person#component[id1,id2]{id1=a1, id2=a2}]
10:29:08,653 DEBUG [WrapVisitor] Wrapped collection in role: test2.Person.accounts
10:29:08,669 DEBUG [DefaultSaveOrUpdateEventListener] saving transient instance
10:29:08,669 DEBUG [AbstractSaveEventListener] generated identifier: component[id1,id2]{id1=a1, id2=a2}, using strategy: org.hibernate.id.Assigned
10:29:08,669 DEBUG [AbstractSaveEventListener] saving [test2.Account#component[id1,id2]{id1=a1, id2=a2}]
10:29:12,638 DEBUG [AbstractFlushingEventListener] flushing session
10:29:12,638 DEBUG [AbstractFlushingEventListener] processing flush-time cascades
10:29:12,638 DEBUG [AbstractFlushingEventListener] dirty checking collections
10:29:12,638 DEBUG [AbstractFlushingEventListener] Flushing entities and processing referenced collections