I guess there is no right or wrong to most patterns, it's just a
matter of taste. My person opinion is that ThreadLocals are a bit of
a hack. I'm an advocate for optimizing interfaces, reducing boiler
plate and minimizing code. But I drew the line when it breaks some
fundamental paradigms.
Readers will have heard me complain about the "returning self" builder
pattern.
new Thing().setOne().setTwo()
Why should the API change so my code can be a little more compact?
There is talk of adding 'returning self' as a language feature. I
can't understand why we don't implement a globally applicable language
feature that doesn't change APIs and works on existing code. Having a
method return (this) at the end is somewhat broken.. If not just plain
strange.
using (new Thing()) { setOne(); setTwo() } // override the default
'this.' within the block.
But that's another thread. :)
I guess ThreadLocal is more of an accepted pattern, even if I don't
like it.
ThreadLocal assumes you code is running on that and only that thread.
It also can cause problem with garbage collection (entities don't get
collected when they should).
On Feb 23, 7:20 am, Christian Hvid <[email protected]> wrote:
> There is a built-in connection pool and you are right; there is no
> overhead in closing and opening a pooled connection.
>
> But you still have to say what database is used. And here it is the
> database the caller is using unless explicitly stated otherwise.
>
> Wrt. ThreadLocal - the way it is used here is a bit like context
> passing in AspectJ.
>
> I don't think it is evil. It is just not commonly used in Java. But it
> has its merits and here it serves the purpose of reducing boiler plate
> code.
>
> On Feb 22, 9:51 pm, Christian Catchpole <[email protected]>
> wrote:
>
> > I think stageful statics are evil. I think ThreadLocal should be cast
> > into a large pit and burried. :)
>
> > Isn't connection management a non-issue in web containers and even
> > stand along apps with a good connection pool. When you open and close
> > a connection, you are just borrowing a slot in a pool. There is no
> > expense to it. In fact the pool will do clever things such as match
> > prepared statements to connections which it has already been prepared
> > on.
>
> > I'm simply suggesting that you might be able to get away with hiding
> > the connection management.
>
> > I'm not trying to discourage your work. I have written a persistence
> > layer which takes a completely different approach again.
>
> > Nice name by the way. :)
>
> > On Feb 23, 5:58 am, Christian Hvid <[email protected]> wrote:
>
> > > :-D
>
> > > Great, exactly.
>
> > > This is the point - it removes a lot of code - it is magic - and thus
> > > smells of ... air - unless you are used to it.
>
> > > You avoid carrying around a JDBC connection object or a reference to
> > > something like jdbcTemplate.
>
> > > Suppose you write a web application and in your servlet code or page
> > > code you have a single try finally block that opens and closes the
> > > database connection.
>
> > > Within that block you call into your business code and your business
> > > code uses various database queries - all against the connection that
> > > you manage with the try catch block.
>
> > > The reason it is a stack of connections and just one connection - is
> > > that a stack allows you to use multiple databases / connections - so
> > > this would work:
>
> > > public long accountBalance(int accountId) {
> > > openConnection("accounting");
> > > try {
> > > return queryScalar(Integer.class, "select balance from account
> > > where id=?", accountId);
> > > } finally {
> > > closeConnection();
> > > }
>
> > > }
>
> > > int accountId = 27;
>
> > > try {
> > > openConnection("logging");
> > > update("insert into log(account_id, balance) values(?, ?)",
> > > accountId, accountBalance(accountId));} finally {
>
> > > closeConnection();
>
> > > }
>
> > > On Feb 22, 7:59 pm, Robert Fischer <[email protected]>
> > > wrote:
>
> > > > Now you've shifted the problem from a plumbing issue to a magical state
> > > > issue. This is a major code
> > > > smell and complicates the API in nonobvious (to the user) ways.
>
> > > > (Of course, I'm the guy who also finalizes his method arguments. So
> > > > I've got some wacky opinions
> > > > relative to Java norms.)
>
> > > > ~~ Robert.
>
> > > > Christian Hvid wrote:
> > > > > But you can leave it up to the caller to open the connection - meaning
> > > > > you just don't open or close any connections.
>
> > > > > public int getUserCount() {
> > > > > return queryScalar(Integer.class, "select count(*) from people");
> > > > > }
>
> > > > > And then have the calling code open and close the connection:
>
> > > > > openConnection();
> > > > > try {
> > > > > ...
> > > > > getUserCount();
> > > > > ...
> > > > > } finally {
> > > > > closeConnection();
> > > > > }
>
> > > > > (The idea is that there is a stack of connections and when you do
> > > > > something you always use the connection at the top of the stack.)
>
> > > > > On Feb 22, 7:24 pm, Robert Fischer <[email protected]>
> > > > > wrote:
> > > > >> The problem is this code:
>
> > > > >> public int getUserCount() {
> > > > >> openConnection();
> > > > >> try {
> > > > >> return queryScalar(Integer.class, "select count(*)
> > > > >> from people");
> > > > >> } finally {
> > > > >> closeConnection();
> > > > >> }
>
> > > > >> }
>
> > > > >> That's 1 semantically meaningful line surrounded by 5 lines of
> > > > >> boilerplate plumbing. Which means
> > > > >> that it's really 1/6th actual code, and 5/6th noise. That's a
> > > > >> pretty poor signal to noise ratio.
>
> > > > >> It's even worse when you're dealing with raw JDBC calls, since you
> > > > >> have to think about preparing
> > > > >> statements and managing connections and data sets and the like.
>
> > > > >> ~~ Robert.
>
> > > > >> Christian Hvid wrote:
> > > > >>> I don't understand - why would that be a problem? (That you have
> > > > >>> explictly open and close your database connection).
> > > > >>> On Feb 22, 7:09 pm, Robert Fischer
> > > > >>> <[email protected]>
> > > > >>> wrote:
> > > > >>>> +1 for Spring JDBC: it manages all that
> > > > >>>> openConnection/closeConnection noise for you, which means
> > > > >>>> that your JDBC code can *also* start to be expressive.
> > > > >>>> ~~ Robert.
> > > > >>>> Rakesh wrote:
> > > > >>>>> have you looked at Spring JDBC? It has a similar interface and
> > > > >>>>> manages
> > > > >>>>> the connections for you.
> > > > >>>>> I think if you go down a non-orm route and want to have lots of
> > > > >>>>> sql,
> > > > >>>>> Ibatis is quite common - not used it so can't say for sure.
> > > > >>>>> Spring JDBC though is very nice and have used it extensively.
> > > > >>>>> Rakesh
> > > > >>>>> On Sun, Feb 22, 2009 at 2:21 PM, Christian Hvid
> > > > >>>>> <[email protected]> wrote:
> > > > >>>>>> Hi Java people.
> > > > >>>>>> I have been toying with simplier ways of doing embedded SQL in
> > > > >>>>>> Java.
> > > > >>>>>> And would like your comments on this one?
> > > > >>>>>>http://code.google.com/p/chalkmine/
> > > > >>>>>> It allows you to write code like this:
> > > > >>>>>> openConnection();
> > > > >>>>>> try {
> > > > >>>>>> int count = queryScalar(Integer.class, "select count(*) from
> > > > >>>>>> people");
> > > > >>>>>> System.out.println("There are "+count+" people in the bin.");
> > > > >>>>>> } finally {
> > > > >>>>>> closeConnection();
> > > > >>>>>> }
> > > > >>>>>> or
> > > > >>>>>> openConnection();
> > > > >>>>>> try {
> > > > >>>>>> List<Person> people = queryList(Person.class, "select name,
> > > > >>>>>> time_in_the_bin from people");
> > > > >>>>>> for (Person p : people)
> > > > >>>>>> System.out.println(p.getName()+" has been
> > > > >>>>>> "+p.getTimeInTheBin()
> > > > >>>>>> +" hours in the bin.");
> > > > >>>>>> } finally {
> > > > >>>>>> closeConnection();
> > > > >>>>>> }
> > > > >>>>>> (Provided that Person has a constructor matching the types of
> > > > >>>>>> name,
> > > > >>>>>> time_in_the_bin. Probably Person(String, int).)
> > > > >>>>>> Where the methods openConnection, queryScalar, queryList,
> > > > >>>>>> closeConnection are statically imported.
> > > > >>>>>> openConnection() figures out the name of the calling class,
> > > > >>>>>> looks up a
> > > > >>>>>> configuration, opens a connection and puts in a ThreadLocal
> > > > >>>>>> container.
> > > > >>>>>> queryScalar(Class, String, ...) performs a query with a single
> > > > >>>>>> row
> > > > >>>>>> result that is "cast" to the given class.
> > > > >>>>>> queryList(Class, String, ...) performs a query and returns the
> > > > >>>>>> result
> > > > >>>>>> as a list of the given class.
> > > > >>>>>> I would like to turn it into a full-fledged open source project.
> > > > >>>>>> But since it is incredibly hard for a new open source project to
> > > > >>>>>> gain
> > > > >>>>>> traction I would like to figure out whether it is interesting
> > > > >>>>>> enough
> > > > >>>>>> first.
> > > > >>>>>> -- Christian
> > > > >>>> --
> > > > >>>> ~~ Robert Fischer.
> > > > >>>> Grails Training http://GroovyMag.com/training
> > > > >>>> Smokejumper Consultinghttp://SmokejumperIT.com
> > > > >>>> Enfranchised Mind Bloghttp://EnfranchisedMind.com/blog
> > > > >>>> Check out my book, "Grails Persistence with GORM and
> > > > >>>> GSQL"!http://www.smokejumperit.com/redirect.html
> > > > >> --
> > > > >> ~~ Robert Fischer.
> > > > >> Grails Training http://GroovyMag.com/training
> > > > >> Smokejumper Consultinghttp://SmokejumperIT.com
> > > > >> Enfranchised Mind Bloghttp://EnfranchisedMind.com/blog
>
> > > > >> Check out my book, "Grails Persistence with GORM and
> > > > >> GSQL"!http://www.smokejumperit.com/redirect.html
>
> > > > --
> > > > ~~ Robert Fischer.
> > > > Grails Training http://GroovyMag.com/training
> > > > Smokejumper Consultinghttp://SmokejumperIT.com
> > > > Enfranchised Mind Bloghttp://EnfranchisedMind.com/blog
>
> > > > Check out my book, "Grails Persistence with GORM and
> > > > GSQL"!http://www.smokejumperit.com/redirect.html
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "The
Java Posse" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/javaposse?hl=en
-~----------~----~----~----~------~----~------~--~---