Hi all,
I'm getting a HibernateException saying "Found two representations of same collection: domain.Email.recipients" when updating a class that's holding a java.util.Set of java.lang.Strings. Doing a Session#save() on the same object works perfect. It's just the Session#update() that's making trouble here.
I tried searching the forum and found a couple of old threads that discussed the same problem but there were no solutions offered. (I also tried reading the auto-translated Russian forum but no luck there either)
Here's all the relevant pieces:
----------------------------------------------------------------------
Hibernate version:
2.1.7c
Mapping documents:
Code:
<hibernate-mapping package="domain">
<class name="Email" table="EMAIL">
<id name="id" type="string" column="id" length="32">
<generator class="uuid.hex" />
</id>
<property name="subject" column="subject" type="string" length="255" />
<property name="body" column="body" type="string" length="10000" />
<set name="recipients" table="EMAIL_RECIPIENT" cascade="all-delete-orphan">
<key column="email_id" />
<element column="recipient_address" type="string" length="100" />
</set>
</class>
</hibernate-mapping>
Database tables:Code:
CREATE TABLE email (
id VARCHAR(32) NOT NULL,
subject VARCHAR(255),
body VARCHAR(1000),
CONSTRAINT email_pkey PRIMARY KEY (id)
);
CREATE TABLE email_recipient (
email_id VARCHAR(32) NOT NULL,
recipient_address VARCHAR(100),
CONSTRAINT fk_email_recipient_to_email FOREIGN KEY (email_id) REFERENCES email (id)
)
Java class being mapped:Code:
public class Email {
private String id;
private String subject;
private String body;
private Set recipients; // contains email addresses as strings
... plus setters and getters for the above
}
Code between sessionFactory.openSession() and session.close():Code:
public class EmailStore implements IEmailStore {
public void update(Email email) {
// using the Thread Local Session design pattern from
// http://www.hibernate.org/42.html
try {
Session session = HibernateSession.beginTransaction();
session.update(email);
session.flush();
HibernateSession.commitTransaction();
} catch (HibernateException e) {
e.printStackTrace(); // this is what prints the below stack trace
HibernateSession.rollbackTransaction();
throw new RuntimeException(e);
}
}
}
Full stack trace of any exception that occurs:Code:
net.sf.hibernate.HibernateException: Found two representations of same collection: domain.Email.recipients
at net.sf.hibernate.impl.SessionImpl.updateReachableCollection(SessionImpl.java:2890)
at net.sf.hibernate.impl.FlushVisitor.processCollection(FlushVisitor.java:32)
at net.sf.hibernate.impl.AbstractVisitor.processValue(AbstractVisitor.java:69)
at net.sf.hibernate.impl.AbstractVisitor.processValues(AbstractVisitor.java:36)
at net.sf.hibernate.impl.SessionImpl.flushEntity(SessionImpl.java:2612)
at net.sf.hibernate.impl.SessionImpl.flushEntities(SessionImpl.java:2478)
at net.sf.hibernate.impl.SessionImpl.flushEverything(SessionImpl.java:2280)
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2259)
at services.storage.EmailStore.update(EmailStore.java:251)
Name and version of the database you are using:PostgreSQL 8.0.0-rc4 (Win32)
The generated SQL (show_sql=true):Code:
select recipients0_.email_id as email_id__,
recipients0_.recipient_address as recipien2___
from EMAIL_RECIPIENT recipients0_
where recipients0_.email_id=?
Debug level Hibernate log excerpt:Code:
12:57:46,576 DEBUG Loader:611 - Initializing object from ResultSet: 1
12:57:46,626 DEBUG Loader:680 - Hydrating entity: domain.Email#1
12:57:46,626 DEBUG StringType:68 - returning 'subject' as column: subject
12:57:46,626 DEBUG StringType:68 - returning 'subject' as column: subject
12:57:46,626 DEBUG StringType:68 - returning 'body' as column: body
12:57:46,626 DEBUG StringType:68 - returning 'body' as column: body
12:57:46,746 DEBUG Loader:294 - done processing result set (1 rows)
12:57:46,746 DEBUG BatcherImpl:210 - done closing: 0 open PreparedStatements, 0 open ResultSets
12:57:46,756 DEBUG BatcherImpl:272 - closing statement
12:57:46,756 DEBUG Loader:314 - total objects hydrated: 1
12:57:46,756 DEBUG SessionImpl:2215 - resolving associations for [domain.Email#1]
12:57:46,766 DEBUG SessionImpl:3982 - creating collection wrapper:[domain.Email.recipients#1]
12:57:46,786 DEBUG SessionImpl:2246 - done materializing entity [domain.Email#1]
12:57:46,786 DEBUG SessionImpl:3149 - initializing non-lazy collections
12:57:46,786 DEBUG SessionImpl:3295 - initializing collection [domain.Email.recipients#1]
12:57:46,786 DEBUG SessionImpl:3296 - checking second-level cache
12:57:46,786 DEBUG SessionImpl:3302 - collection not cached
12:57:46,796 DEBUG BatcherImpl:203 - about to open: 0 open PreparedStatements, 0 open ResultSets
12:57:46,796 DEBUG SQL:229 - select recipients0_.email_id as email_id__, recipients0_.recipient_address as recipien2___ from EMAIL_RECIPIENT recipients0_ where recipients0_.email_id=?
12:57:46,796 DEBUG SQL:229 - select recipients0_.email_id as email_id__, recipients0_.recipient_address as recipien2___ from EMAIL_RECIPIENT recipients0_ where recipients0_.email_id=?
12:57:46,796 DEBUG BatcherImpl:252 - preparing statement
12:57:46,796 DEBUG StringType:46 - binding '1' to parameter: 1
12:57:46,796 DEBUG StringType:46 - binding '1' to parameter: 1
12:57:46,806 DEBUG Loader:402 - result set contains (possibly empty) collection: [domain.Email.recipients#1]
12:57:46,806 DEBUG SessionImpl:3038 - uninitialized collection: initializing
12:57:46,816 DEBUG Loader:277 - processing result set
12:57:46,816 DEBUG Loader:480 - result row:
12:57:46,816 DEBUG StringType:68 - returning '1' as column: email_id__
12:57:46,816 DEBUG StringType:68 - returning '1' as column: email_id__
12:57:46,816 DEBUG Loader:367 - found row of collection: [domain.Email.recipients#1]
12:57:46,816 DEBUG SessionImpl:3061 - reading row
12:57:46,816 DEBUG StringType:68 - returning 'first@foobar.com' as column: recipien2___
12:57:46,816 DEBUG StringType:68 - returning 'first@foobar.com' as column: recipien2___
12:57:46,816 DEBUG Loader:480 - result row:
12:57:46,826 DEBUG StringType:68 - returning '1' as column: email_id__
12:57:46,826 DEBUG StringType:68 - returning '1' as column: email_id__
12:57:46,826 DEBUG Loader:367 - found row of collection: [domain.Email.recipients#1]
12:57:46,826 DEBUG SessionImpl:3061 - reading row
12:57:46,826 DEBUG StringType:68 - returning 'second@foobar.com' as column: recipien2___
12:57:46,826 DEBUG StringType:68 - returning 'second@foobar.com' as column: recipien2___
12:57:46,826 DEBUG Loader:294 - done processing result set (2 rows)
12:57:46,826 DEBUG BatcherImpl:210 - done closing: 0 open PreparedStatements, 0 open ResultSets
12:57:46,826 DEBUG BatcherImpl:272 - closing statement
12:57:46,826 DEBUG SessionImpl:3097 - 1 collections were found in result set
12:57:46,826 DEBUG SessionImpl:3128 - collection fully initialized: [domain.Email.recipients#1]
12:57:46,826 DEBUG SessionImpl:3131 - 1 collections initialized
12:57:46,836 DEBUG SessionImpl:3304 - collection initialized
12:57:47,447 DEBUG JDBCTransaction:37 - begin
12:57:47,447 DEBUG JDBCTransaction:41 - current autocommit status:false
12:57:47,447 DEBUG SessionImpl:1449 - updating [domain.Email#1]
12:57:47,467 DEBUG SessionImpl:1296 - collection dereferenced while transient [domain.Email.recipients#1]
12:57:47,477 DEBUG Cascades:497 - processing cascades for: domain.Email
12:57:47,487 DEBUG Cascades:506 - done processing cascades for: domain.Email
12:57:47,497 DEBUG SessionImpl:2266 - flushing session
12:57:47,497 DEBUG Cascades:497 - processing cascades for: domain.Email
12:57:47,497 DEBUG Cascades:506 - done processing cascades for: domain.Email
12:57:47,497 DEBUG SessionImpl:2459 - Flushing entities and processing referenced collections
12:57:47,537 DEBUG SessionImpl:2553 - Updating entity: [domain.Email#1]
12:57:47,567 DEBUG JDBCTransaction:82 - rollback
12:57:47,567 DEBUG SessionImpl:594 - transaction completion
12:57:47,567 DEBUG SessionImpl:576 - closing session
12:57:47,567 DEBUG SessionImpl:3371 - disconnecting session
12:57:47,567 DEBUG SessionImpl:594 - transaction completion
Big thanks for reading this far!
-Lasse-