Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp
Hibernate version: 3.0.5
Mapping documents:
Code:
<hibernate-mapping package="model.message">
<typedef name="oracle_clob" class="type.OracleClobType"/>
<class name="Template" table="template">
<id name="id" column="id" type="long" unsaved-value="-1">
<generator class="native">
<param name="sequence">template_seq</param>
</generator>
</id>
<version name="version" column="version" type="integer" unsaved-value="negative"/>
<property name="name" column="name" type="string"/>
<joined-subclass name="model.message.email.EmailTemplate" table="email_template">
<key column="id"/>
<property name="from" column="from_addresses" type="string"/>
<property name="to" column="to_addresses" type="string"/>
<property name="cc" column="cc_addresses" type="string"/>
<property name="bcc" column="bcc_addresses" type="string"/>
<property name="subject" column="subject" type="string"/>
<set name="emailTemplateAttachments" where="removed is null or sysdate between added and removed" inverse="true" cascade="all-delete-orphan">
<key column="email_template"/>
<one-to-many class="model.message.email.EmailTemplateAttachment"/>
</set>
<list name="emailTemplateParts" cascade="all-delete-orphan" inverse="false">
<key column="email_template" not-null="true" update="false"/>
<list-index column="list_index"/>
<one-to-many class="model.message.email.EmailTemplatePart"/>
</list>
<joined-subclass name="model.message.email.NewsletterTemplate" table="newsletter_template">
<key column="id"/>
<many-to-one name="newsletter" column="newsletter" class="model.newsletter.Newsletter"/>
</joined-subclass>
</joined-subclass>
</class>
</hibernate-mapping>
Code:
<hibernate-mapping package="model.message.email">
<typedef name="oracle_clob" class="type.OracleClobType"/>
<class name="EmailTemplatePart" table="email_template_part">
<id name="id" column="id" type="long" unsaved-value="-1">
<generator class="native">
<param name="sequence">emailtemplatepart_seq</param>
</generator>
</id>
<version name="version" column="version" type="integer" unsaved-value="negative"/>
<many-to-one name="emailTemplate" column="email_template" class="EmailTemplate" insert="false" update="false" not-null="true"/>
<property name="mimeType" column="mime_type" type="string"/>
<property name="content" column="content" type="oracle_clob"/>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():JSF action method (using HibernateFilter interceptor pattern):
Code:
public String up( )
{
EmailTemplate emailTemplate = _emailTemplatePart.getEmailTemplate( );
List allParts = emailTemplate.getEmailTemplateParts( );
int index = allParts.indexOf( _emailTemplatePart );
if( index > 0 )
{
Collections.swap( allParts, index, index - 1 );
}
return "success";
}
Full stack trace of any exception that occurs: N/A
Name and version of the database you are using: Oracle 9i 9.1.0.2
The generated SQL (show_sql=true): N/A
Debug level Hibernate log excerpt: N/A
It doesn't appear that Collections.swap( ) results in a dirty state for Hibernate List proxies. Invoking this method does result in a swap (it is evident in the rendered JSF view) but calling saveOrUpdate( ) on the emailTemplate object does not effect a change in the database.
I looked at the equalsSnapshot method of PersistentList and it looks like it does a side-by-side comparison of the lists using two iterators, but a lot of that is obfuscated by the call to Type.isDirty( ). The code for EntityType.isDirty( ) calls getIdentifier(old, session) and getIdentifier(current, session) and then calls !getIdentifierType(session).isSame( oldid, newid, session.getEntityMode() ) for comparison.
What that sounds like to me is that as long as both entities are in the session and are unchanged, the isDirty call will return false, even if old.equals( current ) is false. It seems like the return value of the EntityType.isDirty( ) method needs to be:
!getIdentifierType(session).isSame( oldid, newid, session.getEntityMode() ) && !old.equals( new );
or something along those lines. That, or some kind of direct comparison needs to take place in the PersistentList.equalsSnapshot( ) method.
My question is:
1) Am I wrong in my assessment above? (Note: I have implemented similar behavior in version 2.1.7 with no problems)
2) If I am wrong, is there something I can put in my code to force Hibernate to recognize the swap (short of creating a new, non-proxy List object or using non-lazy semantics)
Thanks,
- Jesse