where to put transactions?

2 views
Skip to first unread message

Barry Beattie

unread,
Oct 26, 2007, 2:23:18 AM10/26/07
to cfc...@googlegroups.com
Where to put transactions - I've been down this path before with mixed
results - never been 100% happy.

Previously I've used wrapper transaction functions so I had a choice
how I wanted methods called, etc. Or I've moved the transactions
further and further up the calling stack.


with this example (below) ideally this should be done deep in the
database .... but I haven't that luxury in this case.

what I'll have grief with is that the "gwEval.save(dtoEval);" already
has a transaction so it'll get the correct PKey to return on the
insert. And this is just a simple example.

(NOTE: this uses anemic beans and DAO's while all my gateways are
really for Flash Remoting, not specifically query/multiple record
CFC's.)

it's the gwEval.getByFields
not finding one
returning an empty bean
and gwEval.save(dtoEval) saving the bean.

I'm reluctant to move all that deep into the DAO because either I have
to refer to the other object for that FKey value within the DAO or
pass it in (which means I may be getting it for no reason)

it's not a show-stopper - it's just I don't like any of the solutions
I've come up with so far...

thoughts?
thanx
barry.b


<cfset gwEval = createObject("component","components._evalGateway") />

<!--- START A TRANSACTION HERE (hopes) ----------->

<cfset dtoEval = gwEval.getByFields(courseID="#courseID#",
modID="#modID#").init() />
<cfif len(dtoEval.getevalID()) EQ 0 or dtoEval.getevalID() EQ 0>
<!--- empty/doesn't exist yet --->
<!--- get the default evaluation instrument (needed for a FKey) --->
<cfset dtoInst =
createObject("component","components._instGateway").getByDefault() />
<cfscript>
dtoInst.init();
dtoEval.setEvalID(0); // the flag for "create"
dtoEval.setmodID(modID);
dtoEval.setcourseID(courseID);
dtoEval.setstartdate(now());
dtoEval.setinstID(dtoInst.getInstID());
dtoEval.setevalname("Evaluation For " & modID);
dtoEval.setactive(1);
gwEval.save(dtoEval); /*** has TRANS deep inside ***/
</cfscript>
</cfif>
<!--- at this stage, dtoEval should be either fully populated with
existing data or created from default values --->

<!--- END TRANSACTION HERE (hopes) ----------->

Alan Livie

unread,
Oct 26, 2007, 3:20:55 AM10/26/07
to cfc...@googlegroups.com
I think a service layer is a good place for managing transactions (as others have suggested on this list).

A DAO is good until you need to manage a transaction where more than one object is involved (ie an OrderItemDAO and a TransactionDAO).

In this example you could have a method in the service layer createOrder() that begins the transaction, calls methods on all the objects it needs then closes the transaction.


Alan


________________________________________
From: cfc...@googlegroups.com [cfc...@googlegroups.com] On Behalf Of Barry Beattie [barry....@gmail.com]
Sent: 26 October 2007 07:23
To: cfc...@googlegroups.com
Subject: [CFCDEV] where to put transactions?

Brian Kotek

unread,
Oct 26, 2007, 11:08:22 AM10/26/07
to cfc...@googlegroups.com
+1 for Service layer as the place to manage transactions that span multiple domain objects, or multiple kinds of domain objects.

Barry Beattie

unread,
Oct 26, 2007, 1:02:36 PM10/26/07
to cfc...@googlegroups.com
thanx guys

see, that's my point: you start off thinking "this is just simple CRUD
stuff", a new requirement comes in and the next thing you know you're
refactoring a ton of code and retesting it all... just because of
transactions and the inability to nest them.

Alan Livie

unread,
Oct 26, 2007, 3:38:18 PM10/26/07
to cfc...@googlegroups.com
I'm in the middle of a large refactoring of a messy procedural system so its not a less-messy hybrid of procedural and OO code.

Unfortunately there is still lots of switch and if statements after some of the refactoring.

This seemed Ok until I discovered patterns Strategy and State that could handle these situations very well.

No matter what code I write it always embarrasses me a year or so later.

It's just one of these things I think I have to live with.

Maybe the day I fully understand the book 'Design Patterns' will be the day my code will age well :-)


________________________________________
From: cfc...@googlegroups.com [cfc...@googlegroups.com] On Behalf Of Barry Beattie [barry....@gmail.com]

Sent: 26 October 2007 18:02
To: cfc...@googlegroups.com
Subject: [CFCDEV] Re: where to put transactions?

Phillip Senn

unread,
Oct 26, 2007, 4:23:12 PM10/26/07
to cfc...@googlegroups.com
> No matter what code I write it always embarrasses me a year or so
later.

Oh wow!
What a great life-lesson. I've been pondering lately that 50% of coding
should be taking out the garbage.

Maybe another 10% should be revisiting / refactoring every 6 months.

But as I told a friend who was trying to justify a .5% tax increase:
"Hey!" I said. "I've only got a hundred of those things!"

Sam Larbi

unread,
Oct 27, 2007, 9:33:23 AM10/27/07
to cfc...@googlegroups.com
I'm a big fan of continuous improvement.  When you notice bad code while working on it (or perhaps even near it), make it better.

I don't see any purpose in taking out time to go back and beautify ugly code you haven't touched in six months (or more!) though.  Wait until you need to work on it, then make it better.  If you never work on it again, there was no need to make it better in the first place.

Just my 2 <cfoutput>#smallest_denomination_of_currency_of_your_choice#</cfoutput>.

Sam

Barry Beattie

unread,
Oct 27, 2007, 10:01:44 AM10/27/07
to cfc...@googlegroups.com
On 10/27/07, Sam Larbi <sla...@gmail.com> wrote:
> I'm a big fan of continuous improvement.

I'm not.

I used to be but I'm taking a more pragmatic approach now-a-days.
Sending code into the big bad world, never to see it again, and having
my reputation rest on it's success or otherwise. Get it right, get it
out.

but back to the origional question: looks like there's no magic
bullet, nothing has changed since I last grappled with these problems
(except I'm using Remoting more, making the issue more accute).

it sounds like the only solution is the "big design up-front", where
processes that need to sit within a transaction can be identified and
catered for at the start. not quite as agile as I'd like...

... nesting transactions, that'd fix it. CF9 wishlist perhaps?

oh well...

thanx
barry.b

Brian Kotek

unread,
Oct 27, 2007, 1:36:35 PM10/27/07
to cfc...@googlegroups.com
What sucks is that during the Scorpio beta tour, they told us they had nested transactions working. I'm not sure what happened to cause them to remove it, but that would be such a useful feature that I'm sorry they couldn't keep it in.

Barry Beattie

unread,
Oct 28, 2007, 9:39:49 PM10/28/07
to cfc...@googlegroups.com
yeah, I thought I read that somewhere. Surprised that it didn't make
it since Java has multiple levels of transactions (which, when you
start using them with unit tests and code coverage tools is just soooo
handy)

what's making it tricky is that my beans and DTO's are being generated
by FlexBuilder which I'm then mod'ing. And of course, an insert is
followed by a re-query to get the PK, thanx to the db I'm using - all
within a transaction. I can't even cheat and put both in the same
cfquery tag...

serves me right for using code generators...

no solution here ... just offloading some angst after being cought-out
yet again...

Brian Kotek

unread,
Oct 28, 2007, 10:24:23 PM10/28/07
to cfc...@googlegroups.com
If you're on CF8, you get back the inserted ID automatically when you insert a record.

Aaron Rouse

unread,
Oct 28, 2007, 10:36:53 PM10/28/07
to cfc...@googlegroups.com
That depends on the database you are using.  For example with Oracle it gives you the ROWID which you would then have to still figure out how that relates to your automatically generated PK assuming you are doing automatically generated ones that is.  One could argue with Oracle to just select out your sequence then insert that and not rely on a transaction to get a newly inserted value although I would think transactions are used for more than just getting a newly inserted ID.  If for some reason someone was using Access, it looks like they would get nothing back although one could post a ton of reasons why not to use Access.  Does PGSQL have an autonumbering solution built in? Surprised not to see it listed for this but not used it in so many years that can not remember if it has a way of doing autonumbering

I had yet to try nested transactions with CF8 or read up on them, had just assumed all this time after reading they would be available via the beta that they were in fact there.  Shame they did not make it to the release.
--
Aaron Rouse
http://www.happyhacker.com/
Reply all
Reply to author
Forward
0 new messages