title: Is there a limit for maximum number of concurrent transactions in Hibernate?
body: <p>I've a client that sends 3 requests to a Service Layer which uses Hibernate.</p>
  
  <p>Each single request causes Hibernate to begin a transaction (<code>session.beginTransaction()</code>).</p>
  
  <p>I find that, <strong>sometimes</strong>, one transaction (from the 2+ running concurrent transactions) fails with <code>createQuery is not valid without active transaction</code>.</p>
  
  <p>Here's Hibernate configurations that I use (running in Tomcat 6.0.x and OC4j 10.1.3.4):</p>
  
  <pre><code>&lt;property name="hibernate.connection.pool_size"&gt;5&lt;/property&gt;
          &lt;!--  &lt;property name="hibernate.current_session_context_class"&gt;thread&lt;/property&gt; --&gt;
          &lt;property name="hibernate.current_session_context_class"&gt;org.hibernate.context.ThreadLocalSessionContext&lt;/property&gt;
          &lt;property name="connection.autoReconnect"&gt;true&lt;/property&gt;
          &lt;property name="connection.autoReconnectForPools"&gt;true&lt;/property&gt;
          &lt;property name="connection.is-connection-validation-required"&gt;true&lt;/property&gt;
          &lt;property name="hibernate.show_sql"&gt;true&lt;/property&gt;
          &lt;property name="hibernate.format_sql"&gt;false&lt;/property&gt;
  
          &lt;!-- auto commit --&gt;
          &lt;!-- &lt;property name="connection.autocommit"&gt;true&lt;/property&gt; --&gt;
  
          &lt;!-- configuration pool via c3p0 --&gt;
          &lt;property name="c3p0.idleConnectionTestPeriod"&gt;1000&lt;/property&gt;
          &lt;property name="c3p0.initialPoolSize"&gt;5&lt;/property&gt;
          &lt;property name="c3p0.maxPoolSize"&gt;10&lt;/property&gt;
          &lt;property name="c3p0.maxIdleTime"&gt;1&lt;/property&gt;
          &lt;property name="c3p0.maxStatements"&gt;30&lt;/property&gt;
          &lt;property name="c3p0.minPoolSize"&gt;1&lt;/property&gt;
  
          &lt;property name="cache.use_query_cache"&gt;true&lt;/property&gt;
          &lt;property name="cache.provider_class"&gt;org.hibernate.cache.EhCacheProvider&lt;/property&gt;
          &lt;property name="cache.use_second_level_cache"&gt;true&lt;/property&gt;
  </code></pre>
  
  <p>EDIT: I am using the following Proxy to manage all transactions:</p>
  
  <pre><code>import java.lang.reflect.Field;
  import java.lang.reflect.InvocationHandler;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.lang.reflect.Modifier;
  import java.lang.reflect.Proxy;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.logging.Logger;
  
  import org.hibernate.HibernateException;
  import org.hibernate.Session;
  import org.hibernate.Transaction;
  
  
  /**
   * http://stackoverflow.com/questions/2587702
   * 
   * @author mohammad_abdullah
   */
  public class ServiceProxy implements InvocationHandler {
  
      private Object object;
      private Logger logger = Logger.getLogger(this.getClass().getSimpleName());
      private static final String SESSION_FIELD = "session";
  
      public static final Map&lt;Long, Transaction&gt; ACTIVE_TRANSACTIONS = new HashMap&lt;Long, Transaction&gt;();
  
      private ServiceProxy(Object object) {
          this.object = object;
      }
  
      public static Object newInstance(Object object) {
          return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), new ServiceProxy(object));
      }
  
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  
          Object result = null;
          Session session = null;
          boolean joined = false;
          try {
              if (Modifier.isPublic(method.getModifiers())) {
  
                  session = HibernateUtil.getSessionFactory().getCurrentSession();
  
                  Field sessionField = object.getClass().getSuperclass().getDeclaredField(SESSION_FIELD);
                  if (sessionField == null)
                      throw new UPSAdminException("Service Implementation should have field named: \"" + SESSION_FIELD + "\".");
                  sessionField.setAccessible(true);
                  sessionField.set(object, session);
  
                  if (session.getTransaction().isActive()) {
                      joined = true;
                      logger.info("Using Already Active transaction" + " Method: " + method.getName() + " Thread: "
                              + Thread.currentThread().getId());
                      ACTIVE_TRANSACTIONS.put(Thread.currentThread().getId(), session.getTransaction());
                  } else {
                      logger.info("Transaction Began" + " Method: " + method.getName() + " Thread: " + Thread.currentThread().getId());
                      Transaction newTnx = session.beginTransaction();
                      ACTIVE_TRANSACTIONS.put(Thread.currentThread().getId(), newTnx);
                  }
                  result = method.invoke(object, args);
  
                  if (!joined) {
                      ACTIVE_TRANSACTIONS.get(Thread.currentThread().getId()).commit();
                      ACTIVE_TRANSACTIONS.remove(Thread.currentThread().getId());
                      logger.info("Transaction Commited" + " Method: " + method.getName() + " Thread: " + Thread.currentThread().getId());
                  }
              } else {
                  result = method.invoke(object, args);
              }
  
              return result;
  
          } catch (InvocationTargetException _ex) {
              Throwable cause = _ex.getCause();
              logger.severe("Caller Exception: " + cause + " Method: " + method.getName() + " Thread: " + Thread.currentThread().getId());
  
              if (!joined &amp;&amp; session != null &amp;&amp; session.getTransaction().isActive()) {
                  ACTIVE_TRANSACTIONS.get(Thread.currentThread().getId()).rollback();
                  ACTIVE_TRANSACTIONS.remove(Thread.currentThread().getId());
              }
  
              if (cause instanceof HibernateException) {
                  logger.severe("Hibernate Error. Rollbacked Back. Method: " + method.getName() + " Thread: "
                          + Thread.currentThread().getId());
                  throw new DBException(cause.getCause().getMessage());
  
              } else if (cause instanceof SetRollbackException) {
                  logger.severe("Transaction marked for Rollback. Rollbacked Back. Method: " + method.getName() + " Thread: "
                          + Thread.currentThread().getId());
                  return result;
  
              } else {
                  logger.severe("Error in Business Method : " + method + ". Rollbacked Back." + " Thread: " + Thread.currentThread().getId());
                  throw cause;
              }
          } catch (Exception ex) {
              logger.severe("Error in Proxy code :" + ex + " Method :" + method + " Thread: " + Thread.currentThread().getId());
  
              if (!joined &amp;&amp; session != null &amp;&amp; session.getTransaction().isActive()) {
                  ACTIVE_TRANSACTIONS.get(Thread.currentThread().getId()).rollback();
                  ACTIVE_TRANSACTIONS.remove(Thread.currentThread().getId());
              }
  
              if (ex instanceof HibernateException)
                  throw new DBException(ex.getCause().getMessage());
  
              throw ex;
          }
      }
  }
  </code></pre>