Fire Hibernate custom event listener before auto-triggered default listeners
I made a custom Hibernate Event listener extendin开发者_StackOverflow社区g org.hibernate.event.PreInsertEventListener. The custom listener overrides onPreInsert method and sets a field of a "Contact" entity before saving it in DB with a DAO.
Problem is, the field was null before the listener gives it a value and default hibernate event listeners are automatically triggered BEFORE my custom listener. As they check the ddl, they see the not-null constraint on the field and throw a null check exception before letting my custom event listener give the field its value. (same problem happens when using spring AOP instead of hibernate custom listeners: the default hibernate listener is executed before my aspect method)
So, it is possible to tune the triggering order of the hibernate listeners knowing that I use a spring session factory ?
Thanks
I have an example for you which creates data history for person entity. Hope it helps.
I had to make a helper interface:
public interface DataHistoryAware {
public DataHistory getDataHistory();
public void setDataHistory(DataHistory dataHistory);
}
This is the listener implementation:
public class DataHistoryListener {
@PrePersist
public void setCreateDataHistory(DataHistoryAware model) {
//set creationDate
DataHistory dataHistory = model.getDataHistory() == null ? new DataHistory() : model.getDataHistory();
dataHistory.setCreationDate(new Date());
model.setDataHistory(dataHistory);
}
@PostUpdate
public void setUpdateDataHistory(DataHistoryAware model) {
DataHistory dataHistory = model.getDataHistory() == null ? new DataHistory() : model.getDataHistory();
dataHistory.setLastModificationDate(new Date());
model.setDataHistory(dataHistory);
}
}
The person entity:
@Entity
@EntityListeners(DataHistoryListener.class)
@Table(name="person")
public class Person implements Serializable, DataHistoryAware {
@Column(name = "full_name", length = 255, nullable = false)
private String fullName;
@OneToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "data_history_id", nullable = false)
private DataHistory dataHistory;
public String getFullName() {
return this.fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public DataHistory getDataHistory() {
return dataHistory;
}
public void setDataHistory(DataHistory dataHistory) {
this.dataHistory = dataHistory;
}
}
This implementation creates a datahistory record for person entity before persist, and will update it before merge. The datahistory property has a not-null constraint, so this is the same thing like your problem with the not-null property of the contact entity. Hope it was useful.
IMHO, what you are doing is overkill. You can achieve the same thing with Interceptor
If you already know this and choose to override PreInsetEventListener for some reasons(interest to know), then you need to start from overriding default implementations of org.hibernate.event.def.AbstractSaveEventListener. For example, org.hibernate.event.def.DefaultSaveEventListener.
See that Nullability and foreign key constraint check happens in 'AbstractSaveEventListener.performSaveOrReplicate' and EntityActions are added to the action queue. These actions are executed during session flush and this is when you get call to your PreInsertEventListener from EntityActions.
精彩评论