Uploaded image for project: 'Hibernate ORM'
  1. HHH-12197

On commit, Hibernate reopens and closes additional connection

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 5.2.12
    • Fix Version/s: 5.2.13
    • Component/s: hibernate-core
    • Labels:
      None
    • Bug Testcase Reminder (view):

      Bug reports should generally be accompanied by a test case!

    • backPortable:
      Backport?
    • Last commented by a user?:
      true
    • Sprint:

      Description

      When running in standalone (non JEE) environment with the default Hibernate configuration, I'm seeing this behavior regarding Hibernate's use of underlying DataSource's connections:
      commit() will commit and close the JDBC connection, then it will reopen it, set it to autocommit false and close it immediately.

      I instrumented DataSource and Connection classes to print when their methods are called.

      Here is the full code:

      package hibernate1;
      
      import java.lang.reflect.InvocationHandler;
      import java.lang.reflect.Method;
      import java.lang.reflect.Proxy;
      import java.sql.Connection;
      import java.util.List;
      
      import javax.sql.DataSource;
      
      import org.hibernate.Session;
      import org.hibernate.SessionFactory;
      import org.hibernate.boot.Metadata;
      import org.hibernate.boot.MetadataSources;
      import org.hibernate.boot.registry.StandardServiceRegistry;
      import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
      import org.hibernate.dialect.MySQLDialect;
      
      import com.mysql.cj.jdbc.MysqlDataSource;
      
      public class Hibernate1 {
          
          private static DataSource initDataSource() {
              MysqlDataSource ds = new MysqlDataSource();
              ds.setUrl("jdbc:mysql://localhost:3306/db1");
              ds.setUser("root");
              ds.setPassword("password");
              return ds;
          }
          
          private static DataSource instrumentDataSource(final DataSource ds) {
              return (DataSource) Proxy.newProxyInstance(Hibernate1.class.getClassLoader(), new Class[] { DataSource.class }, new InvocationHandler() {
                  @Override
                  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                      System.out.println("::" + method.getName());
                      if (!method.getName().equals("getConnection")) {
                          return method.invoke(ds, args);
                      } else {
                          final Connection c = (Connection) method.invoke(ds, args);
                          return (Connection) Proxy.newProxyInstance(Hibernate1.class.getClassLoader(), new Class[] { Connection.class }, new InvocationHandler() {
                              @Override
                              public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                  System.out.println(":::" + method.getName());
                                  return method.invoke(c, args);
                              }});
                      }
                  }
              });
          }
      
          private static SessionFactory initHibernate(DataSource ds) {
              StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
                      .applySetting("hibernate.connection.datasource", ds)
                      .build();
      
              Metadata metadata = new MetadataSources(standardRegistry)
                       .addAnnotatedClass( User.class )
                      .getMetadataBuilder()
                      .build();
      
              return metadata.getSessionFactoryBuilder().build();
          }
      
          public static void main(String[] args) throws Exception {
              DataSource ds = instrumentDataSource(initDataSource());
              SessionFactory sf = initHibernate(ds);
              
              Session session0 = sf.openSession();
              System.out.println("# before begin()");
              session0.getTransaction().begin();
              System.out.println("# after begin()");
              List result = session0.createQuery("from User").getResultList();
              System.out.println("# before commit()");
              session0.getTransaction().commit();
              System.out.println("# after commit()");
              session0.close();
          }
      }
      

      And here is the full output:

      Jan 02, 2018 5:33:04 PM org.hibernate.Version logVersion
      INFO: HHH000412: Hibernate Core {5.2.12.Final}
      Jan 02, 2018 5:33:04 PM org.hibernate.cfg.Environment <clinit>
      INFO: HHH000206: hibernate.properties not found
      Jan 02, 2018 5:33:04 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
      INFO: HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
      ::getConnection
      :::getMetaData
      :::getMetaData
      Jan 02, 2018 5:33:04 PM org.hibernate.dialect.Dialect <init>
      INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
      :::close
      # before begin()
      ::getConnection
      :::getAutoCommit
      :::setAutoCommit
      # after begin()
      Jan 02, 2018 5:33:05 PM org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService
      INFO: HHH000397: Using ASTQueryTranslatorFactory
      :::prepareStatement
      # before commit()
      :::commit
      :::isClosed
      :::clearWarnings
      :::close
      ::getConnection
      :::setAutoCommit
      :::isClosed
      :::clearWarnings
      :::close
      # after commit()
      

        Attachments

          Activity

            People

            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: