Pages

Friday, October 30, 2009

Hibernate Interceptors

Share it Please
Consider that we have requirement where we need to trim the values of the strings in the model Object that we are going to save . but if we write a method like trim() which we will call the method by passing a object as an argument which returns the trimmed() values.

but consider , i have defined all the variables in my model classes as private , so we cannot access them in our super class even and cannot change the values [trimming the spaces and reset the values ] , may throw IllegalModifierException,IllegalArgumentException.we need to change all the variable to public .

we may call the code like this ,

SomeObject=trim(SomeObject);
getSession().save(SomeObject);

so we will be calling the trim() method before when ever we say save(),update(),saveOrUpdate() and flush().

so we need to chanage all the values . what happens when we need to save Batch of objects. the trim() method will be called many times.

Lets move for a more generic Option , we will Use the Hibernate Interceptors.

so interceptors provide us a way to process the object before some thing is being done with that object [ may be saved , updated .... ].so how does we write an interceptor .

Consider a MyData model class which i going to save in Databasse , the code looks like this

public class MyData implements Serializable {

@Id@GeneratedValue
public int ID;

public MyData() {
// TODO Auto-generated constructor stub
}

public MyData(String name,String last) {
this.firstName=name;
this.lastName=last;
}

private String firstName;
private String lastName;

public int getID() {
return ID;
}
public void setID(int id) {
ID = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}

}


U can see the some of the variables are set to private .

Now lets write a Basic Interceptor .for this we have a inteceptor interface with some 15 methods . we will use a class "EmptyInterceptor " which already implements the "Interceptor" interface available in hiberante. the code looks like this


@SuppressWarnings("serial")
public class MyDataInterceptor extends EmptyInterceptor {

public boolean onSave(Object entity, Serializable id, Object[] state,
String[] propertyNames, Type[] types) {

for(int i=0;i
if(state[i] instanceof String){
String obtainedValue=(String)state[i];
state[i]=obtainedValue.trim();
}
}//close of loop
return super.onSave(entity, id, state, propertyNames, types);
}

}


what i have done is i just wrote a Interceptor which extends EmptyInterceptor , i implemented a method onSave() [ we have some more methods like onUpdate(),onDelete() and onLoad() .... ] . what this method does is it just perform the code that we have written in the onSave() method before any model class is going to get saved.

consider if we save as above

getSession().save(SomeObject);

before saving the SomeObject , the code in the onSave() method gets exceuted. i have written the code that satisfies our functionality [trimming the String values].

Object entity : the object that we are going to save
Serializable id: The id represents the Serializable primary key (which in our case will bea simple string object).
The state array represents the values of the properties of the persistent object
The propertyNames array holds a list of string values, which are firstName,lastName.

now what i have done , i written a loop which iterates through the state array [ containing values that we are passing ] and trimming them and resetting them.this even works for private variables [ no exception ] .

and final thing as how to link this interceptor to the Hibernate Application ,

Interceptors are 2 types
Global Interceptor : set to SessionFactory
Session Interceptor : set to Session

we will use global since all objects values will be trimmed if they contain strings.

configuration.configure(configFile);
//configuration.setListener("save-update", new DefaultSaveOrUpdateListener());
configuration.setInterceptor(new MyDataInterceptor());
sessionFactory = configuration.buildSessionFactory();

we just need to say configuration.setInteceptor(Our Interceptor class)

and all objects values will be trimmed , with no code changes in any model classes or any additional methods . just a few changes.

No comments :

Post a Comment