Get Connection object while using SessionFactory.getCurrentSession() in Hibernate

Vicky Thakor picture Vicky Thakor · Dec 16, 2016 · Viewed 21.5k times · Source

I'm trying to get Connection object in Hibernate when SessionFactory.getCurrentSession() is used.

Source code

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.internal.SessionImpl;

public class SOExample {
    public static void main(String[] args) throws SQLException {
        Configuration configuration = new Configuration();
        SessionFactory  sessionFactory = configuration.buildSessionFactory(new StandardServiceRegistryBuilder().configure().build());
        Session session = sessionFactory.getCurrentSession();
        Connection connection = ((SessionImpl) session).connection();
        // doing operation on connection object as per my requirement
        DatabaseMetaData databaseMetaData = connection.getMetaData();
        System.out.println(databaseMetaData.getDatabaseProductName());
    }
}

Stacktrace

Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy24 cannot be cast to org.hibernate.internal.SessionImpl
    at com.SOExample.main(SOExample.java:20)

getCurrentSession() gives Proxy object of Session so It can't cast it to SessionImpl so what are the other ways to get Connection object. Or How to SessionImpl from Proxy object.


Other option I tried but it says getConnectionProvider() method not found.

SessionFactoryImplementor sessionFactoryImplementation = (SessionFactoryImplementor) session.getSessionFactory();
ConnectionProvider connectionProvider = sessionFactoryImplementation.getConnectionProvider();
try {
    Connection connection = connectionProvider.getConnection();
} catch (SQLException e) {
    e.printStackTrace();
}

Note: I'm using hibernate-core-5.0.5.Final.jar

Answer

Saulius Next picture Saulius Next · Dec 16, 2016

In Hibenate 5 we need to do things a little bit different (for more details check https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html):

import java.sql.Connection;
import java.sql.SQLException;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.Metadata;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.jdbc.Work;


public class Htest {

    public static void main(String ... args) throws SQLException {
        StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
                .configure("hibernate.cfg.xml")
                .build();

        Metadata metadata = new MetadataSources( standardRegistry )
                .addAnnotatedClass(TesEntity.class)
                .buildMetadata();

        SessionFactory sessionFactory = metadata.getSessionFactoryBuilder()
                .build();

        //one way to get connection version 5.0.2
        Connection c = sessionFactory.
                getSessionFactoryOptions().getServiceRegistry().
                getService(ConnectionProvider.class).getConnection();

        Session sess = null;
        try {
            sess = sessionFactory.getCurrentSession();
        } catch (org.hibernate.HibernateException he) {
            sess = sessionFactory.openSession();
        }


        //If you are using latest version 5.2.3 you can use this line below
        //Connection c =  ((SessionImpl)sess.getSession()).connection();
        System.out.println(c.getMetaData().getDatabaseProductName());

        //another way to get connection
        sess.doWork(new Work() {
            @Override
            public void execute(Connection connection) throws SQLException {
                //connection accessible here
                System.out.println(connection.getMetaData().getDatabaseProductName());
            }
        });
    }
}

My configuration to derby db if you wan to test code.

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
        <property name="hibernate.connection.url">jdbc:derby://localhost:1527/mytest;create=fasle</property>
        <!-- <property name="connection.username"/> -->
        <!-- <property name="connection.password"/> -->

        <!-- DB schema will be updated if needed -->
        <!-- <property name="hbm2ddl.auto">update</property> -->
    </session-factory>
</hibernate-configuration>

Output of this app :

enter image description here