Question

I'm working on a project that requires we are able to modify data on an ORM entity, but not have it persisted back to the database. Essentially, we need to modify the object and pass it in to a service that performs some calculations on the data, and then end the request with none of that data actually being persisted. The catch is that the service that performs the calculations does need to persist some data (run logs, calculation results). This means we can't just clear the whole session once the process has completed.

The entity we're working with is relatively complex (at least a dozen relationships and many more simple properties), so it's not optimal to evict the entity and all of its related entities from the session prior to flushing. To make things more difficult, there are some ormFlush() calls within the service that performs the calculations, which makes manually evicting the entity next to impossible. Due to the large number of relationships, it's not feasible to eager load everything up front and then evict it all before we send it off to the service.

Because of these concerns, I am attempting to open a second Hibernate session (basically, a sandbox) that will never be flushed. We can load the entity and make any changes we need within that session without worrying about the changes persisting to the database.

So far it has been successful with one exception: I'm unable to call the implicit "has" methods (e.g. hasFoo(), hasBar()) on the entity - it results in a NullPointerException.

Example code:

ormSession = ormGetSessionFactory().openSession();
person = ormSession.load( "person", javaCast( "int", 123 ) );

// assume person has a o2m relationship for "brother"
writeOutput( person.hasBrother() );

This results in the following exception:

java.lang.NullPointerException at 
coldfusion.orm.ImplicitRelationUDF.runHasMethodWithNoArgs(ImplicitRelationUDF.java:410) at 
coldfusion.orm.ImplicitRelationUDF.invoke(ImplicitRelationUDF.java:246) at 
coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:431) at 
coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:414) at 
coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2432) at 
cfsean2ecfm1294924799.runPage(C:\websites\test.cfm:11)

My hunch is that ImplicitRelationUDF.java is attempting to use the "standard" CF Hibernate session and is failing because this entity is loaded in a different session, but I don't know how to research further at this point.

I took another approach that still doesn't work, but it's (maybe) food for thought. It throws the same error as the code above.

transaction {
    person = entityLoadByPK( "person", 123 );
    transaction action="rollback";
}

writeOutput( person.hasBrother() );

I'm open to solutions to the specific problem (fixing has*) or the more general problem of modifying an entity and ensuring that the data doesn't get persisted back to the DB.

No correct solution

OTHER TIPS

Set the session default to be readonly

ormSession = ormGetSessionFactory().openSession();
ormSession.setDefaultReadOnly( true );
person = ormSession.load( "person", javaCast( "int", 123 ) );

Anything you call in the session will be readonly

I know the entity you're working with is relatively complex, but all I can think of right now is to write a clone method in it and clone everything it has into a new instance that doesn't attach to any session, and use that pass that cloned instance to your service that requires orm persistent.

There may be better solution but if time is a constraint I'm pretty sure this will work.

How do you deep clone a persistent entity in ColdFusion ORM?

I'd be happy to learn how to deal with this with ORM session, as I've read that it's not implemented well in ColdFusion.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top