Transaction management and Multithreading in Hibernate 4

1.3k views Asked by At

I have a requirement of executing parent task which may or maynot have child task. Each parent and child task should be run in thread. If something goes wrong in parent or child execution the transaction of both parent and child task must be rollback. I am using hibernate4.

2

There are 2 answers

5
Gab On

If I got it, the parent and the child task will run in differents threads.

According to me it's a very bad idea that does not worth considering.

While it may be possible using jta transaction, it's clearly not the case using hibernate transaction management delegation to underlying jdbc connection (you have one connection per session and MUST NOT share an hibernate session between threads).

Using jta you will have to handle connection retrieval and transactions yourself and can't so take advantages of connection pooling and container managed transaction (spring or java ee ones). It may be overcomplicated for about no performance improvments as sharing the database connection between two threads will just probably move the bottleneck one level below.

See how to share one transaction between multi threads

9
Gab On

According to OP expectation here is a pseudo code for Hibernate 4 standalone session management with jdbc transaction (I personnaly advise to go with a container (Java ee or spring) and JTA container managed transaction)

In hibernate.cfg.xml

<property name="hibernate.current_session_context_class">thread</property>

SessionFactory :

Configuration configuration = new Configuration();
configuration.configure("hibernate.cfg.xml");
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
SessionFactory sessionFactory = configuration.buildSessionFactory(builder.build());

The session factory should be exposed using a singleton (any way you choose you must have only one instance for the whole app)

public void executeParentTask() {
  try {
      sessionFactory.getCurrentSession().beginTransaction();

      sessionFactory.getCurrentSession().persist(someEntity);

      myChildTask.execute();

      sessionFactory.getCurrentSession().getTransaction().commit();
  }
  catch (RuntimeException e) {
      sessionFactory .getCurrentSession().getTransaction().rollback();
      throw e; // or display error message
  }
}

getCurrentSession() will return the session bound to the current thread. If you manage the thread execution yourself you should create the session at the beginning of the thread execution and close it at the end.

the child task will retrieve the same session than the parent one using sessionFactory.getCurrentSession()

See https://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch03.html#configuration-sessionfactory

http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html_single/#transactions-demarcation-nonmanaged

You may find this interesting too : How to configure and get session in Hibernate 4.3.4.Final?