There are lots of samples in internet creating audit data for hibernate with Interceptors.
With these samples (maybe I missed some of them) you do not know the order of changes.
We needed to know the order for some reasons.
Luckily our hibernate code was generated with a tool we wrote. We put a method as 1st
line in our setter methods. We were calling a method to understand if this field is changed.
(By this way u can also get full path (stacktrace) of change )
public class User { public void setPersonel( YPerson personel ) { this.setEditedFieldValue( "personel", this.personel, personel, true ) ; this.personel = personel ; } public void setCode( String code ) { this.setEditedFieldValue( "code", this.code, code, true ) ; this.code = code ; } }
Below is the generic code to check if field is changed.
There are cases like
1)Object created with new,we are assigning necessary fields (You do not need to keep ,
because objects former values are null before creation so if an object does not have any audit data,it is same from beginning)
2)Object is being read from database ( We are attaching object so all values will seem null,be careful)
Hibernate creates object with null constructor and calls setters.
3)Object attached , in the flow we changed a field.
protected void setEditedFieldValue( String fieldName, Object oldValue, Object newValue, boolean isNullable ) { //Beans can override isIntercepted method to skip being audited if( !this.isIntercepted( ) ) { return ; } //Do not need to audit initially null ones, or you can skip at time of attaching if( oldValue == null ) { return ; } //for not null int values our code has 0. So if something is not nullable (we know at time of code generation ) // but it is 0 it means null for us return without auditing if( !isNullable ) { if( ( oldValue instanceof Integer ) && ( ( Integer )oldValue ).intValue( ) == 0 ) { return ; } if( ( oldValue instanceof BigDecimal ) && ( ( BigDecimal )oldValue ).compareTo( BigDecimal.ZERO ) == 0 ) { return ; } } //Do not audit if value did not change, //Example : You opened edit page, change some values and some not.So audit only changed ones. if( oldValue == newValue ) { return ; } if( oldValue instanceof YBean ) { String oldDisp = "[N/A]" ; String newDisp = "[N/A]" ; if( YServerConstants.IS_AUDIT_DEBUG_MODE ) { //want to know when if beans are proxy or no. if( HibernateUtils.isproxy( ( YBean )oldValue ) ) { oldDisp = "##BeanProxy##;" + oldValue.getClass( ).getSimpleName( ) + "; id:" + ( ( YBean )oldValue ).getId( ) ; } else { oldDisp = "##YBean##;" + ( ( YBean )oldValue ).getInstanceBeanName( ) + "; id:" + ( ( YBean )oldValue ).getId( ) + "; disp:" + ( ( YBean )oldValue ).getShortDisplay( ) ; } if( newValue != null ) { if( HibernateUtils.isproxy( ( YBean )newValue ) ) { newDisp = "##BeanProxy##;" + newValue.getClass( ).getSimpleName( ) + "; id:" + ( ( YBean )newValue ).getId( ) ; } else { newDisp = "##YBean##;" + ( ( YBean )newValue ).getInstanceBeanName( ) + "; id:" + ( ( YBean )newValue ).getId( ) + "; disp:" + ( ( YBean )newValue ).getShortDisplay( ) ; } } if( !oldDisp.equals( newDisp ) ) { if( this._editedFieldValuesPool == null ) { this._editedFieldValuesPool = new YAuditFieldNameValuePairPool( ) ; } this._editedFieldValuesPool.setFieldValue( fieldName, oldDisp ) ; } } } else { //We do not know if any of objects are null so can not call , o1.equals(02) if( isObjectEquals( oldValue, newValue ) ) { return ; } if( this._editedFieldValuesPool == null ) { this._editedFieldValuesPool = new YAuditFieldNameValuePairPool( ) ; } this._editedFieldValuesPool.setFieldValue( fieldName, oldValue ) ; } } public static boolean isObjectEquals( Object o1, Object o2 ) { if( o1 == o2 ) { return true ; } if( o1 == null || o2 == null ) { return false ; } return o1.equals( o2 ) ; } //This class is holding audit data. Since audits are hold at Arraylist you do not loose order. //Also you can even add stack traces with conditions to monitor your system. public class YAuditFieldNameValuePairPool implements Serializable { protected ArrayList<String> nameList = new ArrayList<String>( 0 ) ; protected ArrayList<Object> valueList = new ArrayList<Object>( 0 ) ; public int setFieldValue( String fieldName, Object value ) { boolean isFound = false ; //check If you have same record do not save again //This is a decision you can think this is usefull to see if //a change is being applied mutiple time. for( int i = this.nameList.size( ) - 1; i >= 0; --i ) { String name = this.nameList.get( i ) ; Object val = this.valueList.get( i ) ; if( name.equals( fieldName ) ) { if( YClientUtils.isObjectEquals( value, val ) ) { isFound = true ; break ; } } } if( !isFound ) { this.nameList.add( fieldName ) ; this.valueList.add( value ) ; return this.nameList.size( ) - 1 ; } return -1 ; }
No comments:
Post a Comment