iBatis better than Hibernate for GUI applications?
Hm, how about this for nose butting? I am going to talk about Java, the language I write an applet with, and iBatis, the ORM I never used. At any rate, this post was forwarded to me, and I found it interesting enough that I think that it deserve a comment.
First, let me run through some things that I do not believe to be correct, and then I will touch the subject in a more general fashion.
That is not the case. Or at least, that sentence is not worded correctly. All the objects that are loaded from the query will be put in the session cache, but there is not reloading done. The session cache is always in memory. This sentence and several others down the road seems to indicate a problem with Hibernate's usage, getting SELECT N+1 or maybe Overly Eager Fetch.
That is not even remotedly close to the way Hibernate works, I must maintain. I do not understand the meaning of reload objects into its session cache, though, reload from where? From the database? Without further information, I can only assume that the mapping for Hibernate were setup incorrectly, and that caused a lot of unneccesary reads.
What does happen before a query is run is that the items are checked for changes, and if there are changes, and if Hibernate detects that they can affect the result of the query, it will persist those changes (assuming you are in AutoFlush mode).
There is a time and place for using SQL in Hibernate, but those are usually very rare edge cases. If you are constantly using SQL in Hibernate, you are doing something wrong. David also mentions that they were building queries using string concatation, which is consider as a big DO NOT DO, that is what the criteria API is for.
Now, for the real issue:
Working with Hibernate or NHibernate in a desktop envrionment can be a little more challanging than on the web. The issue is that you need to make sure that your session doesn't live for the duration of the application. The reason is, of course, the session cache. Using a single session for the application would basically be a memory leak, since the objects would never be released.
Common ways to solve this problem is to use Session per Conversation (think about a wizard or a dialog), to reduce the amount of time that you are keeping items in memory. This is usually something that you need to pay attention to when you load large object graphs, and then you can use the Evict() method to remove it from the session cache.
Personally, I find that it is easier to simply manage the session and not the entities. I would also usually combine this with a file based second level cache, NHibernate has the Prevelance cache that can be used, and I am sure that Hibernate has similar cache implementations.
The book Java Persistence with Hibernate have some information about it, including a sample application that I really ought to port to .Net one day.
I had the pleasure of building several desktop applications that used NHibernate, and I really liked the options that it gave me there (no need to worry about loading too much objects, second level cache that is persistant, etc). In short, you can safely use Hibernate or NHibernate in a desktop application, there are several things that you should be aware of, like the session lifetime, and that you need to close the session at the end of a conversation, but those are simply things to implement, and the benefits are really great.
Comments
I haven't worked with iBatis either, hence I cannot make a judgement, but I've done enough desktop app projects with NHibernate to ensure you that all these statements are bogus, as you already pointed out.
There is one possible problem that might prevent the "lazy guy" from adhering to the session-per-connection pattern which can lead to such a design: You have to know what you need in advance, deffered lazy loading won't work if the session is already closed again. This is partially NHibernates fault as figuring out which object/collection caused a LazyInitialitationException is not always easy as you therefore need to know how and where the object was loaded in first place.
Also using a second level cache in desktop apps is not always a good idea, as cache coherence cannot be guaranteed if you have multiple instances of a particular application working with the same database. That's of course a minor issue when you're only using in-memory databases like sqlite or sqlserver ce.
Regarding your simple things to remember, I almost always use the Spring.NET TransactionProxyFactoryObject which takes care of session and transaction handling. But as always, the more you hide, the more you have to know whats going on behind you.
@Harald,
Actually, NHibernate 1.2 Beta 3 will manage the open/close of the connection for you, so it is much easier to handle the lazy load stuff.
That's true for connections, but you still have to take care for opening/closing your transactions appropriately, whilst the TransactionProxyFactoryObject will decorate particular methods with begin/commit/rollback calls without any further efforts.
Comment preview