hello all,
I'm trying to implement an Interceptor in order to historize inserts/updates on my DB.
I'm still using Hibernate 2 and by the moment cannot move to H3.
I read lots of docs and before trying the triggers/views solution found in
http://blog.hibernate.org/cgi-bin/blosx ... ggers.html I'm trying to implement my own Interceptor based on the sample in
http://hibernate.bluemars.net/Documenta ... nterceptor.
in order to do that I have:
public interface Historizable extends Serializable{
public Set getHistoryEntries();
public void setHistoryEntries(Set set);
}
I have my persister that implements Historizable
I have another persister that's the HistoryElement
I have my HistoryInterceptor where I implemeted all the methods I need.
My first problem is on inserts: my onSave is:
public boolean onSave(Object obj, Serializable id, Object[] newValues, String[] properties, Type[] types) throws CallbackException {
if (!(obj instanceof Historizable)) {
return false;
}
Historizable h = (Historizable) obj;
if (log.isDebugEnabled()) {
log.debug("Inserting " + obj + " with id " + id + " new=" + Arrays.asList(newValues) + " props=" + Arrays.asList(properties));
}
System.out.println("sono Historizable");
// Ensure that the set is not null
Set entries = h.getStoricoEntries();
if (entries == null) {
entries = new HashSet();
h.setHistoryEntries(entries);
}
HistoryEntry entry = new HistoryEntry();
entry.setUser(getUser());
entry.setDate(new Timestamp(new Date().getTime()));
entry.setOperation("created");
entries.add(entry);
return false;
}
when I debug the code I find out that before the invocation of the save() method I have my HistoryEntries set empty and that's right: when the control passes correctly to my onSave() method in my Interceptor it correctly creates the HistoryEntry and puts it in my Historizable object but when the control passes right before the flush() method I find that the history set is again empty so it's like if the history set has not been "persistered".
My other problem is when I try to update: I receive the net.sf.hibernate.TransientObjectException: object references an unsaved transient instance... and I found out the answer that talks about the creation of another Session with the same connection of the "master" session but, truely, I didn't understand it well.
my onFlushDirty() method is
public boolean onFlushDirty(Object obj, Serializable id, Object[] newValues, Object[] oldValues, String[] properties, Type[] types)
throws CallbackException {
System.out.println("onFlushDirty");
if (log.isEnabledFor(Priority.INFO)) {
log.info("Updating " + obj + " with id " + id + " new=" + Arrays.asList(newValues) + " old=" + Arrays.asList(oldValues) + " props="
+ Arrays.asList(properties));
}
if (!(obj instanceof Historizable)) {
return false;
}
Historizable h = (Historizable) obj;
// Won't work:
// net.sf.hibernate.TransientObjectException: object references an unsaved
// transient instance - save the transient instance before flushing:
// de.micromata.hibernate.HistoryEntry
// Set entries = h.getHistoryEntries();
//
// get the copy from the map
Set entries = (Set) histories.get(obj);
for (int i = 0; i < properties.length; i++) {
// Skip the historyEntries
if (properties[i].equals("historyEntries") == true) {
continue;
}
Object oldOne = oldValues[i];
Object newOne = newValues[i];
// Check for changes
if (oldOne == null && newOne == null) {
continue;
}
if (newOne instanceof PersistentCollection) {
// Collections must be compared against the snapshot
PersistentCollection collection = (PersistentCollection) newValues[i];
if (collection.isDirectlyAccessible() == false) {
continue;
}
// retrieve Snapshot
oldOne = collection.getCollectionSnapshot().getSnapshot();
if (oldOne instanceof Map && newOne instanceof Set) {
// a Set is internally stored as Map
oldOne = ((Map) oldOne).values();
}
}
if (oldOne != null && oldOne.equals(newOne) == true) {
continue;
}
// Generate a new entry
HistoryEntry entry = new HistoryEntry();
entry.setUser(getUser());
entry.setDate(new Timestamp(new Date().getTime()));
entry.setOperation("update");
entry.setProperties(properties[i]);
entry.setOldValue(format(oldOne));
entry.setNewValue(format(newOne));
if (log.isDebugEnabled()) {
log.debug("Changed " + properties[i] + " from " + oldOne + " to " + newOne);
}
// and store it.
entries.add(entry);
}
// h.setHistoryEntries(entries);
return false;
}
How can I solve these problems? I already used Hibernate for a project that didn't need historicization so it's my first time trying to historize all the "updates/inserts" in my DB.
thx in advance for any help