session.connection() объявлен устаревшим в Hibernate?

Нам нужно иметь возможность получить связанные java.sql.Connection зимней сессии. Никакое другое соединение не будет работать, так как это соединение может быть связано с выполняющейся транзакцией.

Если метод session.connection() устарел, как я могу это сделать?

14 ответов

Решение

Теперь вы должны использовать Work API:

session.doWork(
    new Work() {
        public void execute(Connection connection) throws SQLException 
        { 
            doSomething(connection); 
        }
    }
);

Или в Java 8:

session.doWork(connection -> doSomething(connection)); 

Если session.connect() сейчас не рекомендуется, как я должен это сделать?

Вы должны использовать Session#doWork(Work) и Work API, как упомянуто в Javadoc:

connection()
Устаревшее. (планируется удалить в 4.x). Замена зависит от необходимости; за прямое использование JDBC doWork(org.hibernate.jdbc.Work); для использования "временного сеанса" (TBD).

У вас есть некоторое время до Hibernate 4.x, но использование устаревшего API выглядит следующим образом:

альтернативный текст:)

Обновление: в соответствии с RE: [hibernate-dev] прокси-сервер Соединения в списке hibernate-dev, кажется, что первоначальное намерение устареть было препятствовать использованию Session#connection() потому что он был / считается "плохим" API, но должен был остаться в то время. Я думаю, они изменили свое мнение...

Попробуй это

((SessionImpl)getSession()).connection()

На самом деле getSession возвращает тип интерфейса сеанса, вы должны увидеть исходный класс для сеанса, набрать тип в исходном классе и получить соединение.

УДАЧИ!

Это то, что я использую и работает для меня. Загрузите метод Session в SessionImpl и легко получите объект подключения:

SessionImpl sessionImpl = (SessionImpl) session;
Connection conn = sessionImpl.connection();

где session имя вашего объекта сеанса Hibernate.

Вот способ сделать это в Hibernate 4.3, и это не рекомендуется:

  Session session = entityManager.unwrap(Session.class);
  SessionImplementor sessionImplementor = (SessionImplementor) session;
  Connection conn = sessionImplementor.getJdbcConnectionAccess().obtainConnection();

Есть еще один вариант с большим количеством приведений, но по крайней мере он не нуждается в рефлексии, который вернет вам проверку времени компиляции:

public Connection getConnection(final EntityManager em) {
  HibernateEntityManager hem = (HibernateEntityManager) em;
  SessionImplementor sim = (SessionImplementor) hem.getSession();
  return sim.connection();
}

Конечно, вы можете сделать это еще "красивее" с помощью нескольких instanceof проверяет, но версия выше у меня работает.

Я нашел эту статью

package com.varasofttech.client;

import java.sql.Connection;
import java.sql.SQLException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.SessionImpl;
import org.hibernate.jdbc.ReturningWork;
import org.hibernate.jdbc.Work;

import com.varasofttech.util.HibernateUtil;

public class Application {

public static void main(String[] args) {

    // Different ways to get the Connection object using Session

    SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
    Session session = sessionFactory.openSession();

    // Way1 - using doWork method
    session.doWork(new Work() {
        @Override
        public void execute(Connection connection) throws SQLException {
            // do your work using connection
        }

    });

    // Way2 - using doReturningWork method
    Connection connection = session.doReturningWork(new ReturningWork<Connection>() {
        @Override
        public Connection execute(Connection conn) throws SQLException {
            return conn;
        }
    });

    // Way3 - using Session Impl
    SessionImpl sessionImpl = (SessionImpl) session;
    connection = sessionImpl.connection();
    // do your work using connection

    // Way4 - using connection provider
    SessionFactoryImplementor sessionFactoryImplementation = (SessionFactoryImplementor) session.getSessionFactory();
    ConnectionProvider connectionProvider = sessionFactoryImplementation.getConnectionProvider();
    try {
        connection = connectionProvider.getConnection();
        // do your work using connection
    } catch (SQLException e) {
        e.printStackTrace();
    }
}
}

Это помогло мне.

connection() просто устарела на интерфейсе. Это все еще доступно на SessionImpl, Вы можете сделать то, что делает Spring, и просто назвать это.

Вот код из HibernateJpaDialect весной 3.1.1

public Connection getConnection() {
        try {
            if (connectionMethod == null) {
                // reflective lookup to bridge between Hibernate 3.x and 4.x
                connectionMethod = this.session.getClass().getMethod("connection");
            }
            return (Connection) ReflectionUtils.invokeMethod(connectionMethod, this.session);
        }
        catch (NoSuchMethodException ex) {
            throw new IllegalStateException("Cannot find connection() method on Hibernate session", ex);
        }
    }

С Hibernate >= 5.0 вы можете получить Connection как это:

Connection c = sessionFactory.
getSessionFactoryOptions().getServiceRegistry().
getService(ConnectionProvider.class).getConnection();

Для hibenate 4.3 попробуйте это:

public static Connection getConnection() {
        EntityManager em = <code to create em>;
        Session ses = (Session) em.getDelegate();
        SessionFactoryImpl sessionFactory = (SessionFactoryImpl) ses.getSessionFactory();
        try{
            connection = sessionFactory.getConnectionProvider().getConnection();
        }catch(SQLException e){
            ErrorMsgDialog.getInstance().setException(e);
        }
        return connection;
    }

Попробуй это:

public Connection getJavaSqlConnectionFromHibernateSession() {

    Session session = this.getSession();
    SessionFactoryImplementor sessionFactoryImplementor = null;
    ConnectionProvider connectionProvider = null;
    java.sql.Connection connection = null;
    try {
        sessionFactoryImplementor = (SessionFactoryImplementor) session.getSessionFactory();
        connectionProvider = (ConnectionProvider) sessionFactoryImplementor.getConnectionProvider().getConnection();
        connection = connectionProvider.getConnection();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return connection;
}
    Connection conn = null;
    PreparedStatement preparedStatement = null;
    try {
        Session session = (org.hibernate.Session) em.getDelegate();
        SessionFactoryImplementor sfi = (SessionFactoryImplementor) session.getSessionFactory();
        ConnectionProvider cp = sfi.getConnectionProvider();
        conn = cp.getConnection();
        preparedStatement = conn.prepareStatement("Select id, name from Custumer");
        ResultSet rs = preparedStatement.executeQuery();
        while (rs.next()) {
            System.out.print(rs.getInt(1));
            System.out.println(rs.getString(2));
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (preparedStatement != null) {
            preparedStatement.close();
        }
        if (conn != null) {
            conn.close();
        }
    }

Если вам нужно возвращаемое значение изнутри лямбды, не упускайте из видуdoReturningWork()

      try {
  return session.doReturningWork(connection -> {
    try (CallableStatement cs = connection.prepareCall(...)) {
      cs.doSomethingPseudoMethod();
      cs.executeUpdate();
      return cs;
    }
  });
} catch (SQLException sqlException) {
  ...
}

Вот метод Java 8 для возврата Connection используется EntityManager фактически ничего не делая с ним:

private Connection getConnection(EntityManager em) throws SQLException {
    AtomicReference<Connection> atomicReference = new AtomicReference<Connection>();
    final Session session = em.unwrap(Session.class);
    session.doWork(connection -> atomicReference.set(connection));
    return atomicReference.get();
}
Другие вопросы по тегам