« 10 Myths About Designers | Main | Design by Committee »

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a0120a4c5681a970b0120a5339c29970b

Listed below are links to weblogs that reference ColdFusion 9 & ORM: Overkill?:

Comments

Feed You can follow this conversation by subscribing to the comment feed for this post.

By the way, one feature of ORM that I am also aware of is database independance; that is, the ORM knows how to talk to different databases, so using ORM you are not tied to any given database technology.

However, I am discounting that feature here, because in web development, you don't typically switch databases after you develop your application.

My top three reasons:

1. Streamlines development. You mention you already have tools to write CRUD, I presume this means you have tools to write your standard sprocs (per earlier blog posts). Not knowing your tools I cannot compare them to an ORM tool like Hibernate to know whether it provides more features or not. As I said in some of my sproc posts, using an ORM tool with sprocs for your reads defeats a major (but not the only) benefit. You could still see significant development time and maintenance cut, but I couldn't say with what I know.

2. Performance. Most ORM tools worth their salt have built in caching, which is amazing. Hibernate has 2 levels of caching, something called the first level, or session cache, and the other logically enough is the second level cache.

Whenever you "do stuff" (work with the DB), you do so in a "session". Don't confuse with the old ASP-style sessions. This is basically a thread-local session for the life of your thread (which may be just a couple milliseconds for an easy operation, or many seconds or minutes if the thread is doing heavy lifting). While your thread has its own session, objects are automatically cached and managed (you can tweak of course). Therefore, if your code looks up object foo once, and then later looks it up again, Hibernate automatically knows the object is in cache (you can set typical cache things like TTL) and doesn't re-query. If you dirty something in your session, Hibernate knows and does the appropriate thing. If you are really paranoid about certain objects being changed by other threads at the same time you can force a query, but I can tell you, running thousands of queries per second against data, we haven't had any issues with dirty reads.

The second level cache is cross-thread and you can use it for things like lookup tables. Again, you define the size (i.e. store only 1000 rows in memory) and TTL. In Java world, this cache is either unique to each JVM, or you can use specialized cache providers (that plug into Hibernate) which coordinate the cache across separate JVMs, so if one JVM dirties an object in the second level cache, all JVMs second level caches will know about it and re-read from the DB next time it is cached. But basically, say goodby to lookup table queries finally!

But, you may say, this is not important because when you do a query you do one query and join everything together, well, that still costs DB time, and see my 3rd point.

3. Lazy loading. If you have table 1 which foreign keys to table 2, you can define a lazy or greedy load. This means, if you say "get row 5 from table 1", if you define greedy, a join will be done and the appropriate object from table 2 is loaded in the same query execution. If you say lazy, then table 2 is only loaded IF you access table 2 from the table 1 object. If you never access table 2, the query is never done, saving DB time (and memory in the app server). This is all automatic, you configure it once per object (table) and you are done. Of course, you can override any global configurations for individual queries if you want.

--------------------

#2 and #3 can be done outside of an ORM tool, but Hibernate puts it in one nice package. #1 is something unique to an ORM tool, but if you have essentially developed your own generator (or don't want to use prepared SQL), then it can fall apart. Also, a lot of the other features of Hibernate (not mentioned here) will only become very useful if you do a significant amount of business logic processing at your app layer. If all your app does is read information from a DB and return it to a UI, then the 3 items above are your big benefits. If you do not have worries about your app being the best performing it can be, then #2 and #3 aren't going to be a huge interest.

Here is a good site that isn't overwhelming that shows example code: http://www.javaworld.com/javaworld/jw-10-2004/jw-1018-hibernate.html

BTW, there are Hibernate tools that can generate you the configuration XML files and POJOs (or persistent classes) by pointing them at a DB. So really, once you get your first try down, after that, somebody can give you a brand new, foreign DB, and you can be fully up and running in a matter of seconds, probably similiar to what you do with your sproc generator.

I know about lazy loading, but honestly, don't feel it's a big enough issue to merit the switch to ORM.

Likewise, I see that with ORMs like Hibernate, to filter queries you basically pass in SQL like statements (HQL)... this is clearly a turn off for me -- basically SQL in the application code! That seems like a backwards step to me.

Take a look at Ben Forta's article, linked above and here again. Scroll down to the section of code he exhibits for filtering the data:


While this is ColdFusion markup, that "authorid=10" bit, I assume, is HQL... basically, SQL in your code again, outside the DAL... that's essentially spaghetti code once more, and I don't see why you'd want that? It's simple in Ben's example, but imagine a complex set of filters and the string that would create!

What am I missing? Why would you have ORM, yet be taking a step backwards by putting all that pseudo SQL code back into other layers of your application code???

I attempted to paste Ben's specific code that I'm referencing, and pasted it as HTML, which hid it. Here it is:

<!--- Get data --->
<cfset data=EntityLoad("Books", {authorid=10})>

The whole point of ORM is to abstract the data layer from you application logic. You don't want to mix your beatiful and pure java code with nasty kinky SQL. So if you are using HQL to filter stuff you already started bad. If you do Hibernate, you can use criteria for filters, which is a way more ellegant solution. I guess David already mentioned the good reasons to use an ORM, but I'll try one more. If you take products like Hibernate (for example), you make use of a very well finished product, supported by a wide community. I mean, no offense, but chances are that if you write your own (sprocs generator whatever) it won't be as good as Hibernate - I'm talking performance, features, robustness, everything. It's like a Relational Database. "Why use Oracle ? I can write my own !" Yeah, right...

@Budd: "Likewise, I see that with ORMs like Hibernate, to filter queries you basically pass in SQL like statements (HQL)..." We rarely use HQL. Read up on "criteria" and you'll see some powerful things. Basically, it as simple as saying "criteria.add(Foo.attribute, 'the value')". You can also do a "criteria.in" or "criteria.gt" (greater than), etc. It is possible the CF implementation is a bit different, the code he is posting is definitely not native Hibernate code (nor is it HQL, HQL looks near 100% identical to SQL, except instead of table and column names, you use object and object attribute names).

Frankly though, I don't see his code being anything like SQL, it just happens there is a left hand side and a right hand side, which any programming language has. My hope in his implementation is the EntityLoad line wouldn't blow out into something like ("Books", {(authorid=10} or {authorid=11}) and {firstName like '%Joe'})) if you needed to do multiple things. If it does, I agree, that it a poor implementation of ORM.

Here is how you can load an object by primary key with Hibernate (which is what Ben is doing I think)

session.load( Message.class, new Long(1) )

This will load the Message object (presumably maps to a Message table) that has the PK of 1 (which is a numeric data type). Logically equivalent to what Ben did with the CF implementation, he just replaced the comma with an equal sign, and doesn't use a strongly typed value.

Here is a good example on criteria querying. It shows you the wrong way to do it (essentially building an HQL query which isn't much better than just building a SQL string with bound variables), and how much better it is using a criteria. You won't see any resemblence to SQL.

http://www.javalobby.org/articles/hibernatequery102/?source=archives

The author also uses the built-in paging capabilities (.setFirstResult and .setMaxResults combined together allow you to do paging of data) and shows how you can set the eager and lazy fetching.

It's too early to tell for sure, so I can't say which of Hibernate's features are present in ColdFusion 9. We may just be too early to see all of them in use.

For example, here is another ColdFusion expert's example of ORM and using it to do paging of results... it has some HQL as well as other stuff in there that I don't feel is all that elegant:

http://www.coldfusionjedi.com/index.cfm/2009/8/14/Simple-ColdFusion-9-ORM-Paging-Demo

Now, to be fair, he never says he's being elegant; he's clearly going for "simple". But he does make a case for one line of code he uses, stating that it's a "perfect example of HQL use", and to me, it's just SQL in your code again, which is BAD for many reasons.

The paging is equivalent in concept, you set the page size, and essentially start position. As you can see from my previous post, the start position is defined as setFirstResult (so if 10 per page and you want page 2, you start at number 11). Of course, you can abstract that out however you want. In our system, apps actually specify the page number they want and since we know the page size, the math is easy to figure out.

BTW, he doesn't have to use HQL to get the count, he can do a criteria query with what is called a projection, which does a count. And you only need to do the count of records if you want to return the caller the total number of records (or pages). To figure out the records to query for page 2, you shouldn't have to do a count (at least you don't have to with native Hibernate).

Here is the code:

criteria.setProjection(Projections.rowCount());

It returns you a number, as you'd expect. So yes, he is being lazy.

@Dave: The problem is, I don't know if ColdFusion 9 implements everything, or just a custom implementation and interface to Hibernate's underlying engine. I can't find anything on whether or not the Criteria API is supported, for example.

Regardless, as to the original intent of this article, I'm still riding the fence about the benefits of implementing ORM at Pelco, or if we're better off staying put with the stored procedure methodology we currently employ...

I agree, if the CF implementation is gimped enough, and if you have a firm sproc design for selects, ORM may not pose a big enough benefit to warrant the investment.

It is definitely a different style of thinking. I guess the only thing I can say is if you are really interested in it, give it a whirl during some "free time". While poking around to see what others had to say on the subject, I came across a CF Hibernate DAO design. In my limited knowledge of CF, this looks similiar to a standard Java design which works well for many.

http://bears-eat-beets.blogspot.com/2009/08/hibernate-coldfusion-9-and-daos.html

The guy also mentions AOP in passing (ColdSpring I guess is the implementation), I didn't know CF had AOP (or a Spring framework around it). That's another very cool technology to look into. I kind of which we went all the way with Spring...

http://www.coldspringframework.org/

I would *not* discount platform independence as a useful feature of an ORM for web developers. And it's *not* because of switching databases once an application is written, it's because of selling applications to other people. Yes, it's true, a lot of us work on bespoke applications, where all the code is custom and belongs ultimately to the client (or to ourselves), but imo that's a vanishing market. The markets will increasingly demand applications that can be licensed, whether that's an OS license or a commercial license, and then placed on the client's server. Many large clients are already standardized on a particular database, and while they may like and even want your application, it's *not* going to convince them to switch from Oracle to SQL Server (or vice versa). So for my part I think the smart thing to do is to write applications that can be loaded onto whatever database the client wants. And DataFaucet, the ORM I developed, even installs the tables for you. :)

This is what i call innovation technology as everything is taken care of in fast forward way.

I think you have a thorough understanding in this matter. You describe in detail all here.

Verify your Comment

Previewing your Comment

This is only a preview. Your comment has not yet been posted.

Working...
Your comment could not be posted. Error type:
Your comment has been posted. Post another comment

The letters and numbers you entered did not match the image. Please try again.

As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

Having trouble reading this image? View an alternate.

Working...

Post a comment