I ran into an odd one today. The initial problem is a bit of a newbie one, but the side effect was not what I expected.
Here I am trying to create a Transaction object and then assign it to the Transfer object (it’s a one-to-one realtionship) before saving it.
<cftransaction> <cfset tx = new com.test.orm.Transactions() /> <cfset tx.setClientID(10010) /> <!--- Set others ---> <!--- Forget to call entitySave(tx)! ---> <cfset transfer = new com.test.orm.Transfers() /> <!--- Assign transaction to the transfer ---> <cfset transfer.setTransaction(tx) /> <cfset transfer.setMerchantID(1) /> <!--- etc. ---> <cfset entitySave(tr) /> </cftransaction>
This blows up because I didn’t call
entitySave() on my first object before I assigned it to the second. The error is:
object references an unsaved transient instance – save the transient instance before flushing: Transactions
However, despite the ORM flush happening on when I close the transaction block the transfer record is actually created with a NULL transactionID – not what I expected!
It seems that if the error is thrown by Hibernate, despite the code being in a transaction block – there is no guarantee the transaction will be rolled back fully.
The work-around seems to be to put make a call to
ormFlush() as the last thing in the transaction block. That causes the a full roll back, and I can see it due to the identity increment skipping numbers in the database.