session.connection () застарілий у режимі глибокого сну?


80

Ми повинні мати змогу отримати пов’язані java.sql.Connectionз сеансом сплячого режиму. Жодне інше з’єднання не буде працювати, оскільки це з’єднання може бути пов’язане із запущеною транзакцією.

Якщо session.connection () тепер застарілий, як я повинен це робити?


Якщо хтось захоче прочитати більше про це: hibernate.onjira.com/browse/HHH-2603
WW.

9
Однією з багатьох причин триматися подалі від цієї жахливої ​​системи називається сплячий режим. Час йому спати назавжди, як випливає з назви.
chrisapotek

2
@chrisapotek Вам не подобається Hibernate ... чи є у вас якісь альтернативи, чи ви пишете всі наполегливі речі від руки?
Emaborsa

1
Як щодо mybatis?
Geoffrey Ritchey

Відповіді:


86

Тепер потрібно використовувати Work API:

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

Або в Java 8+:

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

1
Мені не подобається використовувати застарілі речі, але, мабуть, це вагомий привід почати їх використовувати. Але я не знав про Work API. Дуже дякую.
TraderJoeChicago

1
Ого. Я використовую Hibernate 3.2.7.ga, але мій org.hibernate.Session НЕ має жодного методу doWork. Це чудово!
TraderJoeChicago

25
гак, що негарно. Люди завжди будуть потребувати необробленого зв'язку для чогось - вони повинні це зробити легко.
Пітер

9
SessionImpl sessionImpl = (SessionImpl) session; Connection conn = sessionImpl.connection();Потім ви можете використовувати об'єкт підключення в будь-якому місці, де вам це потрібно, у цьому коді, а не лише в невеликому методі.
Саймон Мбатія,

2
Ще коротше в Java8 - session.doWork(this::doSomething). Якщо ви хочете повернути результат - використовуйте doReturningWork ()
Optio

22

Якщо session.connect()зараз застарілий, як я повинен це робити?

Ви повинні використовувати Session#doWork(Work)і WorkAPI, як зазначено в Javadoc:

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

У вас є деякий час до Hibernate 4.x, але, добре, використання застарілого API якось виглядає так:

текст заміщення:)

Оновлення: Відповідно до RE: [hibernate-dev] Проксі-сервер підключення у списку hibernate-dev, схоже, початковим наміром припинення було перешкоджати використанню, Session#connection()оскільки це було / вважається "поганим" API, але це повинен був залишитися на той час. Думаю, вони передумали ...


2
Мій Javadoc тут дещо відрізняється від вашого. Тільки трохи менш зрозуміло: для заміни на SPI для виконання роботи проти з’єднання; заплановано вивезення в 4.x. Ваш JavaDoc говорить все. Цей JavaDoc нічого не говорить.
TraderJoeChicago

@ Серджо Дійсно. Але якщо я можу, ви повинні згадати такі важливі речі, як версія Hibernate, яку ви використовуєте у своєму питанні. Ваша версія досить стара (javadoc Session#connection()у Hibernate Core 3.3 згадує про альтернативу), і це, як правило, читачі не можуть здогадатися.
Pascal Thivent

@Pascal Версія 3.2.7.ga - це остання версія, яку я міг знайти на Maven. GroupId = org.hibernate та artifactId = сплячий режим. Цікаво, чи може Maven надати останню версію, чи просто потрібно скопіювати банку та ігнорувати maven.
TraderJoeChicago

@Sergio Це тому, що ви використовуєте старий монолітний jar ( hibernate), а не hibernate-coreякий має новіші версії. А для остаточних версій (3.5.x) вони доступні у сховищі JBoss Nexus .
Паскаль Тивент,

1
@Pascal Дякую! Одна велика проблема полягає в тому, що мені потрібно передати зв’язок, тому якщо Hibernate не зможе надати мені свій зв’язок, це буде погано. Мені потрібно буде отримати цей зв’язок іншим способом. Думаю, хто б не мав такої ідеї припинити спосіб підключення, повинен подумати ще раз.
TraderJoeChicago

12

Спробуйте це

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

Насправді getSession повертає тип інтерфейсу сеансу, ви повинні побачити, що таке оригінальний клас для сеансу, введіть тип, відтворений до початкового класу, і отримайте з'єднання.

ЩАСТИ!


1
❤️ uuuuu, так це неприємно, це потрібно - намагаючись налаштувати мою програму для встановлення з’єднань лише для читання, щоб розповсюджувати між репліками для читання. Дякую.
Сем Беррі

1
Чому у цього немає більше голосів? Чи є якісь причини цього не робити? Для мене ідеально працює

@tilper SessionImplзнаходиться у внутрішньому пакеті Hibernate (тому не призначений для використання), а також це залежить від фактичної реалізації. Крім того, ви не можете легко знущатись над сеансом у своїх тестах, коли ви його кинете.
Вік

9

Існує ще один варіант, в якому задіяно все ще багато приводів, але принаймні він не потребує роздумів, що поверне вам перевірку часу компіляції:

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

Звичайно, ви можете зробити це навіть "гарнішим" за допомогою декількох instanceofперевірок, але версія вище працює для мене.


9

Ось спосіб зробити це в Hibernate 4.3, і він не є застарілим:

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

1
Чи безпечно конвертувати sessionв SessionImplementor?
macemers

@DerekY, я знаю, що це старе, але зараз я маю справу з цим. І ТАК, це так. Усі реалізації сеансу також є якимось чином SessionImplementor.
Реджиндо Сантос,

9

Це те, що я використовую і працює для мене. Знизьте об’єкт Session у SessionImpl і отримайте об’єкт підключення легко:

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

де session- ім’я об’єкта сеансу Hibernate.


8

connection()був просто застарілим на інтерфейсі. Він все ще доступний на SessionImpl. Ви можете робити те, що робить Весна, і просто називати це.

Ось код 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);
        }
    }

15
Це те, що змушує вас робити надзвичайну сплячку. Мало фреймворків так погано, як Hibernate.
chrisapotek

8

Я знайшов цю статтю

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();
    }
}
}

Мені це допомогло.


6

З Hibernate> = 5.0 ви можете отримати ось Connectionтаке:

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

3

Для 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;
    }

1

Спробуйте це:

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;
}

0
    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();
        }
    }

0

Ось метод 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();
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.