I'm writing a journalling interceptor that will selectively store column-level changes to a journal table. I'm using the findDirty() method and comparing the incoming states. While debugging, I noticed that while the currentState, previousState and types arrays are "aligned" correctly (i.e. each array element at corresponding indices refers to the same property), the propertyNames array is "off". The ordering of the first three arrays seems to be driven off the ordering of the properties in the hbm.xml file. But, the propertyNames array seems to be driven off the ordering of the getters and setters in the persisted class file.
This looks like a bug because I can "align" my bean getters/setters with my mapping file and make the code work correctly. If coerced, I suppose I could through together a "quick" main to demonstrate this phenomenon.
Here's the mapping file:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="gov.llnl.ais.util.db.hibernate.JournalTestBean" table="JRNL_TEST">
<id name="id" type="long" column="JRNL_TEST_ID">
<generator class="sequence">
<param name="sequence">rr.RR_GLOBAL_INTR_NO_SEQ</param>
</generator>
</id>
<!-- properties -->
<!-- "wrong" -->
<!--
<property name="string" column="JRNL_TEST_TXT" />
<property name="number" column="JRNL_TEST_NO" />
<property name="date" column="JRNL_TEST_DT" />
<property name="string2" column="JRNL_TEST_TXT_2" />
-->
<!-- "right" -->
<property name="date" column="JRNL_TEST_DT" />
<property name="number" column="JRNL_TEST_NO" />
<property name="string" column="JRNL_TEST_TXT" />
<property name="string2" column="JRNL_TEST_TXT_2" />
</class>
</hibernate-mapping>
Here's the persisted class (test class):
Code:
package gov.llnl.ais.util.db.hibernate;
import java.io.Serializable;
import java.util.Date;
/**
* mapped to JRNL_TEST table to debug/test JournalInterceptor
*
* created: Jan 11, 2004 9:26:47 PM
* @author Nick Dellamaggiore
*/
public class JournalTestBean implements Serializable
{
private static final long serialVersionUID = 1L ;
private Long id ;
private String string ;
private int number ;
private Date date ;
private String string2 ;
public JournalTestBean()
{
super();
}
public Date getDate()
{
return date;
}
public void setDate(Date date)
{
this.date = date;
}
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public int getNumber()
{
return number;
}
public void setNumber(int number)
{
this.number = number;
}
public String getString()
{
return string;
}
public void setString(String string)
{
this.string = string;
}
public String getString2()
{
return string2;
}
public void setString2(String string2)
{
this.string2 = string2;
}
}
Here's the findDirty method:
Code:
public int[] findDirty(
Object entity,
Serializable id,
Object[] currentState,
Object[] previousState,
String[] propertyNames,
Type[] types)
{
//localSwitch not being set means TRUE(shouldn't happen but just in case)
if( JournallingConfig.getInstance().getGlobalSwitch() &&
getLocalSwitch() &&
JournallingConfig.getInstance().isJournaled( entity.getClass() ) ) {
//we have some interest in this object but we still don't know if of the changed
//properties are actually important to us, loop through them to find out.
ArrayList journalInfoList = new ArrayList() ;
for( int i = 0 ; i < currentState.length ; i++ ) {
//if the property is to be journal and it has changed.
if( JournallingConfig.getInstance().isJournaled( entity.getClass(), propertyNames[i] ) &&
( ( currentState[i] != null && !currentState[i].equals( previousState[i] ) ) ||
( previousState[i] != null && !previousState[i].equals( currentState[i] ) ) ) ) {
journalInfoList.add( createJournalInfo( entity, currentState[i], previousState[i], propertyNames[i], types[i]) ) ;
}
}
if( journalInfoList.size() > 0 ) {
for( Iterator iterator = journalInfoList.iterator() ; iterator.hasNext() ; ) {
JournalInfo journalInfo = null ;
try {
journalInfo = (JournalInfo)iterator.next() ;
HibernateSession.currentSession().save( journalInfo ) ;
} catch (HibernateException e) {
log.error("Unable to write journalling info for " + journalInfo ) ;
}
}
}
}
//null => default hibernate behavior
return null ;
}