Reputation: 37916
I've just started learning Hibernate and I use the following pattern (from documentation) for every transaction:
private Session session;
private Transaction transaction;
protected List selectAll(Class clazz) throws HibernateException {
List objects = null;
try {
session = MyHibernateHelper.getSessionFactory().openSession();
transaction = session.beginTransaction();
// SELECT ALL
objects = session.createCriteria(clazz).list();
transaction.commit();
} catch (HibernateException exc) {
if (transaction != null) transaction.rollback();
throw exc;
} finally {
session.close();
}
return objects;
}
I can accept that every operation should be wrapped in a transaction. But it seems to me strange and unnecessary to rollback select
, in case it fails.
I think I can safely remove catch
block from the above example. And from any read-only operation. Am I right?
Upvotes: 12
Views: 2444
Reputation: 96395
Consider Hibernate has to work with all kinds of databases for all kinds of situations. What they're giving you in their documentation is how to use Hibernate from any supported database. And they try to support a lot of databases. Some of these databases might handle cleaning up failed transactions without needing an explicit rollback, but Hibernate wants to make sure it covers everybody.
Also consider having a read-only transaction fail is going to be extremely rare in real life. Once it does happen there isn't going to be much for the rollback to do, but what it does do -- releasing locks as Marc B points out -- is not something you want to skip. So what you're advocating is a very tiny optimization (based on how infrequently that path gets exercised) which could have bad consequences in some circumstances. Having a lock not get released is the kind of bad consequence that doesn't manifest until some other transaction fails or hangs, making it very hard to track down the cause. The lock not getting released could cause deadlocks so the performance/availability impact could be dire. Also this would be a pain to test for, if there is a problem it would be likely to be missed until there's a crisis in a production environment. On multiple counts it's the kind of thing you want to avoid.
The biggest problem here is that there's a lot of boilerplate code to include for every transaction. My suggestion is to either implement some utility methods using callbacks or the Command pattern (see Bauer and King's book Java Persistence with Hibernate for examples), or adopt a framework. There is an argument against frameworks that they obscure implementation details and make learning harder, but you've already had the learning experience of seeing how these pieces are put together. There are mature frameworks like Seam or Spring that will handle this for you.
Upvotes: 9
Reputation: 1854
If you use a framework or API or what ever is not really under your control, you should always respect their failure strategy because you don't know how it internally works. May be there are other resources to free.
Upvotes: 1