PostInsert() not persisting entity

24 views
Skip to first unread message

Tristan Lee

unread,
Jan 26, 2015, 6:20:22 PM1/26/15
to cf-or...@googlegroups.com
On the entities that I want to track changes, they extend AuditableEntity.cfc which contain all of the pre/post handlers.

Inside postInsert(), a new AuditLog entity is created, properties set, and the entity is saved. However, this does not persist to the database nor do I see any SQL in the logs that would indicate it even tried.

public void function postInsert( any entity ) {

if (structKeyExists(variables, "updateMementos")) {
var oAuditLog = entityNew('AuditLog');

oAuditLog.setRowID(getIdentityValue());
oAuditLog.setRowData(variables.updateMementos.current);
oAuditLog.setTableName(getTableName());
oAuditLog.setChangeType('create');

entitySave(oAuditLog);
}
}

The ORM session settings are as follows:
this.ormSettings = {
cfclocation = [ "/models" ],
dbcreate = "none",
logSQL = true,
flushAtRequestEnd = false,
autoManageSession = false,
eventHandling = true,
skipCFCWithError = false
};

Flushing is managed manually since everything wrapped in a transaction so it can be sure validation was successful before persisting.

In the postInsert(), any attempts to ORMFlush() and wrap entitySave(oAuditLog) within a transaction result in an error message saying it was unable to persist the parent entity (even though it actually succeeded). I am stumped for a solution here. Do I need to create a new ORM session to handle this audit save?

Tristan Lee

unread,
Jan 27, 2015, 9:06:02 AM1/27/15
to cf-or...@googlegroups.com
Another thing to add is I tried this within a new session on Railo, and the following works:

public void function postInsert() {

if (structKeyExists(variables, "updateMementos")) {

// create a new hibernate session
// (not sure why this doesn't work with current session)
var hbSession = ormGetSessionFactory().openSession();
var tx = hbSession.beginTransaction();

var oAuditLog = entityNew('AuditLog');
oAuditLog.setRowID(getIdentityValue());
oAuditLog.setRowData(variables.updateMementos.current);
oAuditLog.setTableName(getTableName());
oAuditLog.setChangeType('insert');

try {
hbSession.save(oAuditLog);
tx.commit();
} catch (any e) {
tx.rollback();
} finally {
hbSession.flush();
hbSession.close();
}
}
}

This does not work for ACF though. Railo can handle passing the CF entity to .save() where as ACF throws an exception. Every place I am using ORM it's wrapped within a transaction block so I can't figure out why a new transaction here does not persist.

Nando Breiter

unread,
Jan 27, 2015, 9:20:15 AM1/27/15
to cf-or...@googlegroups.com
I ran into a similar problem on ACF, and after struggling gave up and reverted to using an sql insert statement within preUpdate(), leveraging the old data struct available at that point, which contains the state of the entity before it was updated. Verbose, but it works reliably to maintain the audit trail I need.



Aria Media Sagl
Via Rompada 40
6987 Caslano
Switzerland

+41 (0)91 600 9601
+41 (0)76 303 4477 cell
skype: ariamedia


--
You received this message because you are subscribed to the Google Groups "cf-orm-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cf-orm-dev+...@googlegroups.com.
To post to this group, send email to cf-or...@googlegroups.com.
Visit this group at http://groups.google.com/group/cf-orm-dev.
For more options, visit https://groups.google.com/d/optout.

Tristan Lee

unread,
Jan 27, 2015, 9:36:16 AM1/27/15
to cf-or...@googlegroups.com
That's yet another issue I ran in to. I have a many-to-many relationship on one of my entities. It uses a hierarchy model where the Department entity has a many-to-many to Centers. So if I want to assign a new Center to a Department, I simply do Department.addCenter(new Center(...)); However, because that relationship change happens only on the link table and not the Department entity itself, no (pre/post)Update event is invoked since the state of Department never changed.

In that case, I can't even use a standard INSERT statement because the event is never fired. :-\

Tristan Lee

unread,
Jan 27, 2015, 10:05:35 AM1/27/15
to cf-or...@googlegroups.com
On Tuesday, January 27, 2015 at 9:20:15 AM UTC-5, Nando Breiter wrote:
Well, here was the hack that works in Railo and ACF10. Putting this in its own thread allowed for a new transaction since it appears to be a new Hibernate session and for it to persist properly. Then, I check for an exception in the thread and "rethrow" it, which will rollback the previous transaction.

public void function postInsert() {

if (structKeyExists(variables, "updateMementos")) {

// HACK: for whatever reason, this entity will not persist in the current session
// so putting it in a thread and watching for exceptions is the workaround
thread name="tAuditLog#createUUID()#" action="run" entity=this data=variables.updateMementos.current {
transaction {
oAuditLog = entityNew('AuditLog');
oAuditLog.setRowID(entity.getIdentityValue());
oAuditLog.setRowData(data);
oAuditLog.setTableName(entity.getTableName());
oAuditLog.setChangeType('insert');
entitySave(oAuditLog);
}
}
thread action="join";

// throw an exception if the thread did not complete
// this rolls back the previous transaction
if (structKeyExists(cfthread[structKeylist(cfthread)], "error")) {
throw (attributeCollection=cfthread[structKeylist(cfthread)].error);
}
}
}
Reply all
Reply to author
Forward
0 new messages