1

My Java application uses Hibernate as an ORM framework. I find myself often writing code like this:

Session session = HibernateUtil.getSessionFactory().openSession();
try {
    session.beginTransaction();

    // do some work, which might or might not yield a result which will be returned
    doWork(session);
    // it also might involve using and changing local variables, like success and failure counters

    session.getTransaction().commit();
    return result;
} catch (Exception e) {

    // optional: log the exception
    Utility.logException("some log node", e);
    // Also, some other actions like sending an alert email might happen at this place.

    if (session.getTransaction().isActive()) {
        session.getTransaction().rollback();
    }

    // optional: rethrow the exception
    //throw e;
} finally {
    if (session.isOpen()) {
        session.close();
    }
}

and I'm wondering if there is a good way to put this 'boilerplate' code in a single method. The doWork often (but not always) involves modifying local variables.

If this was a C# application, I'd just create a method like this:

public static void DoWorkInSession(Action<Session> workToDo, String logNode, bool rethrowException)

and call the workToDo Action inside the method.

Using reflection (which I already do at some places) only resolves the problem partially, and makes logging errors less convenient with the 'InvocationTargetException's. Are there any other (better) ways to do this, e.g. using Java 8 functionalities which I'm slowly beginning to discover?

2

Make use of inheritance.

This code already follows the Template Method pattern, with doWork() being the method called by the template. Turn this code into an abstract superclass and subclass all of your Hibernate access methods from it.

Or better, use a template that's provided by a third-party library, and which avoids problems such as session.close() throwing a masking exception. One possibility is Spring's HibernateTemplate, and you might find Spring's declarative transaction management beneficial as well.

Or, if you're opposed to Spring, there are other alternatives. I'm currently working on a project that uses Guice with MyBatis, which I don't particularly like, but YMMV.

If you really want to use Java8 features, rather than a template method you could define the boilerplate to accept a Function, which is then passed each row from a ResultSet. But I'd rather go with something that has a wide user base.

  • Thanks; I don't understand why I didn't think of making an abstract SessionTask class, especially given that I've used similar constructions before. The HibernateTemplate is a step too far right now but might be useful in the future. – Glorfindel Apr 24 '17 at 8:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.