Squeryl/Record transactions *Squeryl users please read*

221 views
Skip to first unread message

David Whittaker

unread,
Jun 9, 2011, 7:10:20 PM6/9/11
to liftweb
I've been looking into a few issues involving Squeryl/Record and Lift transactions (DB.use) recently.  The two main issues I see are 1) There is no way to detect when a Lift transaction ends in order to clean up external resources and 2) Squeryl doesn't have the concept of more than one DB in use per application.  One solution would be to add the appropriate integration points in the Lift transaction lifecycle and accept that Squeryl won't completely support all DB.use features, but I wonder if this is really necessary.  For the Squeryl/Record users out there, how many of you are using Lift transactions as opposed to Squeryl transactions?  If you are using Lift transactions, why did you choose them?  If I were to add better integration of Squeryl transactions with Lift (think SquerylRecord.buildLoanWrapper) does anyone see a need to maintain the Lift transaction support?  Is there a feature of Lift transactions that you need that Squeryl doesn't offer, or are any of you using Squeryl and Mapper side by side?  I'm far from a decision on this and I'd like some feedback from the community on what you all think would be best.

Ján Raska

unread,
Jun 10, 2011, 2:43:38 AM6/10/11
to lif...@googlegroups.com
Hi Dave,

I'll be speaking for myself and Kajo. You've already heard some of these answers from me, but you'll have it at one place at least...

On Jun 10, 2011, at 1:10 , David Whittaker wrote:

> I've been looking into a few issues involving Squeryl/Record and Lift transactions (DB.use) recently. The two main issues I see are 1) There is no way to detect when a Lift transaction ends in order to clean up external resources and 2) Squeryl doesn't have the concept of more than one DB in use per application.

I'm not happy to hear that. I'm preparing one feature that I was thinking would use and connect to second DB

> One solution would be to add the appropriate integration points in the Lift transaction lifecycle and accept that Squeryl won't completely support all DB.use features, but I wonder if this is really necessary. For the Squeryl/Record users out there, how many of you are using Lift transactions as opposed to Squeryl transactions?

We don't use Lift transactions any more...

> If you are using Lift transactions, why did you choose them?

We chose it as it seemed easier, coming from Mapper world.

> If I were to add better integration of Squeryl transactions with Lift (think SquerylRecord.buildLoanWrapper) does anyone see a need to maintain the Lift transaction support?

IMHO no, there isn't. It took me about half an hour to switch (just rewrite initialization, custom loan wrapper and place transaction{} instead of DB.use at places where I needed specific transactions) and it provides me everything I need so far.

> Is there a feature of Lift transactions that you need that Squeryl doesn't offer, or are any of you using Squeryl and Mapper side by side?

Possibly connection pooling but that can be achieved by other means. And it'd be nice to have multiple DBs

> I'm far from a decision on this and I'd like some feedback from the community on what you all think would be best.
>

> --
> You received this message because you are subscribed to the Google Groups "Lift" group.
> To post to this group, send email to lif...@googlegroups.com.
> To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.

Jeppe Nejsum Madsen

unread,
Jun 10, 2011, 3:48:01 AM6/10/11
to lif...@googlegroups.com

We're not using Squeryl atm, but I'm considering it (or something
else) in the future

We've started out with Mapper (and thus Lift transactions) since it
was fast & easy to get something up and running but as complexity
grows, the ActiveRecord style is not really sufficient anymore and so
we're gradually moving more towards a CQRS-like architecture.

I know nothing about the Squeryl transactions yet, but would think
there could be some value (for us at least :-) to be able to use
Mapper & Squeryl side by side

/Jeppe

David Whittaker

unread,
Jun 10, 2011, 9:26:05 AM6/10/11
to lif...@googlegroups.com
On Fri, Jun 10, 2011 at 2:43 AM, Ján Raska <ras...@gmail.com> wrote:
Hi Dave,

I'll be speaking for myself and Kajo. You've already heard some of these answers from me, but you'll have it at one place at least...

On Jun 10, 2011, at 1:10 , David Whittaker wrote:

> I've been looking into a few issues involving Squeryl/Record and Lift transactions (DB.use) recently.  The two main issues I see are 1) There is no way to detect when a Lift transaction ends in order to clean up external resources and 2) Squeryl doesn't have the concept of more than one DB in use per application.

I'm not happy to hear that. I'm preparing one feature that I was thinking would use and connect to second DB

After thinking about it a bit, I think I was wrong to put it that way.  It's not that Squeryl can't be used with multiple DBs, it just isn't aware of them in the way Lift is (e.g. ConnectionIdentifiers and DBVendors).  In Squeryl land you only have one SessionFactory, but it doesn't need to return Session instances that reference the same DB each time.  There isn't anything stopping you from doing something like:

SquerylRecord.initWithSquerylSession(
  if(db1InUse)
    Session.create(
        DriverManager.getConnection("jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1", "sa", ""), new H2Adapter))
  else
    Session.create(
        DriverManager.getConnection("jdbc:h2:mem:db2;DB_CLOSE_DELAY=-1", "sa", ""), new H2Adapter)))

In other words, the parameter to initWithSquerylSession is a call by name which is invoked to "vend" a Session object.  There is no reason it can't look at some application state to decide which DB to access, you just need to manage that state yourself.
 

> One solution would be to add the appropriate integration points in the Lift transaction lifecycle and accept that Squeryl won't completely support all DB.use features, but I wonder if this is really necessary.  For the Squeryl/Record users out there, how many of you are using Lift transactions as opposed to Squeryl transactions?

We don't use Lift transactions any more...

>  If you are using Lift transactions, why did you choose them?

We chose it as it seemed easier, coming from Mapper world.

> If I were to add better integration of Squeryl transactions with Lift (think SquerylRecord.buildLoanWrapper) does anyone see a need to maintain the Lift transaction support?

IMHO no, there isn't. It took me about half an hour to switch (just rewrite initialization, custom loan wrapper and place transaction{} instead of DB.use at places where I needed specific transactions) and it provides me everything I need so far.

>  Is there a feature of Lift transactions that you need that Squeryl doesn't offer, or are any of you using Squeryl and Mapper side by side?

Possibly connection pooling but that can be achieved by other means. And it'd be nice to have multiple DBs


That's a good point.  There are several good third party connection pools out there though (c3p0, dbcp, bonecp) and if we did decide to discontinue Lift transaction support I could definitely write up some examples in the wiki.

David Whittaker

unread,
Jun 10, 2011, 9:38:09 AM6/10/11
to lif...@googlegroups.com
We're not using Squeryl atm, but I'm considering it (or something
else) in the future

We've started out with Mapper (and thus Lift transactions) since it
was fast & easy to get something up and running but as complexity
grows, the ActiveRecord style is not really sufficient anymore and so
we're gradually moving more towards a CQRS-like architecture.


Glad to hear you're thinking of giving Squeryl a try Jeppe.  If you have any questions as you make your decision I'd be happy to try to answer them for you.
 
I know nothing about the Squeryl transactions yet, but would think
there could be some value (for us at least :-) to be able to use
Mapper & Squeryl side by side


To me, right now, that seems like it would be the biggest loss.  You could use both even if Squeryl/Record didn't make use of Lift's transaction, but if you are using LoanWrappers you'd end up starting 2 transactions per request and there might be some issues with Squeryl and Mapper doing updates within separate transactions.  Both would commit at the requests end or rollback on exception but I worry about the order of commits.  Do you think that might be an issue for you?
 
/Jeppe

David Whittaker

unread,
Jun 14, 2011, 11:49:42 AM6/14/11
to lif...@googlegroups.com
On Fri, Jun 10, 2011 at 2:43 AM, Ján Raska <ras...@gmail.com> wrote:
I'm not happy to hear that. I'm preparing one feature that I was thinking would use and connect to second DB

Ján,

Just wanted to point out for you and anyone else who is interested in using Squeryl with more than one DB that Max gave a much better explanation on how to do it than mine on the Squeryl list:


All,

I'm a bit surprised that I haven't gotten more reaction to this.  Are most of you using Squeryl transactions already rather than DB.use style? 

Ján Raska

unread,
Jun 14, 2011, 2:41:30 PM6/14/11
to lif...@googlegroups.com
On Jun 14, 2011, at 17:49 , David Whittaker wrote:

On Fri, Jun 10, 2011 at 2:43 AM, Ján Raska <ras...@gmail.com> wrote:
I'm not happy to hear that. I'm preparing one feature that I was thinking would use and connect to second DB

Ján,

Just wanted to point out for you and anyone else who is interested in using Squeryl with more than one DB that Max gave a much better explanation on how to do it than mine on the Squeryl list:


Thanks a lot Dave, I haven't been at Squeryl's list for a few days. It really looks cool, I'll try it out for sure.


All,

I'm a bit surprised that I haven't gotten more reaction to this.  Are most of you using Squeryl transactions already rather than DB.use style? 


Peter Brant

unread,
Jun 14, 2011, 2:55:38 PM6/14/11
to lif...@googlegroups.com
Hi David,

Just for another data point, we're using Squeryl transactions and
multiple databases (w/o Record though). We're using basically the
approach Max outlines above. It is wrapped in our own API though to
make it easier to stub out transaction management in a test
environment.

I do vaguely remember some issues with DB.use when we first got
started, but my recollection is vague enough that I didn't think it
was worth chiming in. It could have been user error too.

Pete

David Whittaker

unread,
Jun 14, 2011, 4:15:52 PM6/14/11
to lif...@googlegroups.com
Hi Pete,

I appreciate the feedback.  There definitely are  issues with DB.use and Squeryl and I wouldn't be surprised if they contributed to whatever problem you had.  

At this point, based on the feedback I've seen I'm leaning towards deprecating DB.use support in Lift 2.5 and concentrating my efforts on better integration of Squeryl transactions through constructs like a LoanWrapper and better documentation (including connection pooling options).  If anyone out there feels like that's a bad direction to head in now would be a good time to express yourself.

Dave Gurnell

unread,
Jun 15, 2011, 4:50:09 AM6/15/11
to lif...@googlegroups.com
Hi Dave,

+1 to the loanwrapper model for running transactions.

Out of curiosity, does you approach mean separating the notions of connecting to a database and starting a transaction? This would be really useful for e.g. acceptance testing, where the tests are running in a separate process from the code under test. In other words:

beginAcceptanceTest {
connectToDatabase {
// This line runs in its own one-line transaction:
val user = User.createRecord.save

// The web site can see data created on the previous line even though we haven't disconnected from the DB:
makeRemoteWebSiteDoSomething

withTransaction {
// Code in here runs in a transaction, so just for the sake of illustration:
var otherUser = User.createRecord.save

// The web site *wouldn't* be able to see otherUser because the transaction isn't committed:
makeRemoteWebSiteDoSomething
}

// etc ...
}
}

As far as I can tell this is a drawback with DB.use (I've inferred this myself rather than read it anywhere, so apologies if I've misunderstood how DB.use works).

Cheers,

-- Dave

David Whittaker

unread,
Jun 15, 2011, 4:29:38 PM6/15/11
to lif...@googlegroups.com
Hi Dave,

I didn't entirely follow your code, but since you are already using Squeryl transactions I think that what you want to do is already possible.  Squeryl has both the transaction{} and inTransaction{} blocks.  The latter will "join" a transaction if one already exists but the former will always start a new transaction and commit it (or roll it back) at the end of the block.  You can nest as many of these as you'd like.  So I think what you might want to do is to just wrap your user creation in a transaction block:

transaction{
  val user = User.createRecord.save
}

That way it will occur in a transaction of its own.  Check the Squeryl doc for more info: http://squeryl.org/sessions-and-tx.html

Reply all
Reply to author
Forward
0 new messages