Here's the scenario:
Classes:
public class HtmlSite
{
private String name;
private List<HtmlPage> pages;
public String getName() { return name;}
public String setName( String name ) {this.name = name};
public List<HtmlPage> getPages() { return pages; }
public void setPages( List<HtmlPage> pages) { this.pages = pages; }
}
public class HtmlPage
{
private String name;
public String getName() { return name;}
public String setName( String name ) {this.name = name};
}
Hibernate mappings:
<class name="HtmlSite">
<property name="name" type="string" column="st_name"/>
<bag name="pages" cascade="all-delete-orphan">
<key column="pg_st_id"/>
<one-to-many class="HtmlPage"/>
</bag>
</class>
<class name="HtmlPage">
<property name="name" type="string" column="pg_name"/>
</class>
Here's the scenario:
public void savePage( final HtmlSite site, final HtmlPage page )
{
// site is an unchanged, detached instance, so reassociate it
HibernateUtil.getSession().lock( site, LockMode.NONE );
// check to see if the page exists in the site's pages
// if not, add it.
if ( !site.getPages().contains( page ) )
site.getPages().add( page );
site.setName( Long.toString( System.currentTimeMillis() );
page.setName( Long.toString( System.currentTimeMillis() );
HibernateUtil.beginTransaction();
HibernateUtil.getSession().saveOrUpdate( site );
HibernateUtil.getSession().flush();
HibernateUtil.commitTransaction();
}
Here's the problem - if the page already exists in the site's pages collection, the change appears in the entity, but is not commited to the database. If the locking step is skipped, the save works correctly. Unfortunately, the lock is necessary as the pages collection is lazy and may not have been initilized when this method is invoked.
Regardless of whether the site is locked or not, the name changes is reflected in the database. However, if a lock is in place, changes to the page children of the site are not committed.
Note: regardless of whether the site is locked or not, additions to and removals from the pages collection are reflected correctly in the database. It's merely an issue with updated objects that already exist in the pages collection.
|