【问题标题】:session.connection() deprecated on Hibernate?session.connection() 在 Hibernate 上已弃用?
【发布时间】:2011-04-01 09:24:03
【问题描述】:

我们需要能够获得休眠会话的关联java.sql.Connection。没有其他连接将起作用,因为此连接可能与正在运行的事务相关联。

如果 session.connection() 现在已被弃用,我应该怎么做?

【问题讨论】:

  • 如果有人想了解更多信息:hibernate.onjira.com/browse/HHH-2603
  • 远离这个名为 Hibernate 的糟糕框架的众多原因之一。顾名思义,是时候让它永远沉睡了。
  • @chrisapotek 你不喜欢 Hibernate...你有其他选择吗?还是你自己写所有持久化的东西?
  • mybatis怎么样?

标签: java hibernate orm


【解决方案1】:

您现在必须使用 Work API:

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

或者,在 Java 8+ 中:

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

【讨论】:

  • 我不喜欢使用已弃用的东西,但我想这是开始使用它的好理由。但我不知道 Work API。非常感谢。
  • 哇。我正在使用 Hibernate 3.2.7.ga 但我的 org.hibernate.Session 没有任何 doWork 方法。太好了!
  • 太丑了。人们总是需要原始连接来做某事——他们应该让它变得简单。
  • SessionImpl sessionImpl = (SessionImpl) session; Connection conn = sessionImpl.connection(); 然后,您可以在代码中其他任何您需要的地方使用连接对象,而不仅限于一个小方法。
  • 在 Java8 中更短 - session.doWork(this::doSomething)。如果你想返回一个结果 - 使用 doReturningWork()
【解决方案2】:

如果 session.connect() 现在已被弃用,我该怎么做?

您必须使用 Session#doWork(Work)Work API,如 Javadoc 中所述:

connection()
已弃用。(计划在 4.x 中删除)。更换视需要而定;做直接 JDBC 的东西使用 doWork(org.hibernate.jdbc.Work);用于打开“临时会话”使用 (TBD)。

您在 Hibernate 4.x 之前还有一段时间,但是,使用不推荐使用的 API 看起来像这样:

:)

更新: 根据 hibernate-dev 列表中的 RE: [hibernate-dev] Connection proxying 看来,弃用的最初意图是不鼓励使用 Session#connection(),因为它被/被认为是一个“坏”的 API,但它应该留在那个时候。我猜他们改变主意了……

【讨论】:

  • 我的 Javadoc 与您的略有不同。只是不太清楚:被替换为 SPI 以执行针对连接的工作;计划在 4.x 中删除。您的 JavaDoc 说明了一切。这个 JavaDoc 什么也没说。
  • @Sergio 确实如此。但是,如果可以的话,您应该提及重要的事情,例如您在问题中使用的 Hibernate 版本。你的版本已经很老了(Hibernate Core 3.3 中Session#connection() 的 javadoc 提到了替代方案),这通常是读者无法猜测的。
  • @Pascal 版本 3.2.7.ga 是我在 Maven 上能找到的最新版本。 GroupId = org.hibernate 和 artifactId = hibernate。不知道maven能不能提供最新的版本还是只需要复制jar就可以忽略maven。
  • @Sergio 那是因为您使用的是旧的整体 jar (hibernate),而不是具有更新版本的 hibernate-core。对于终极版本 (3.5.x),它们在 JBoss Nexus repository 中可用。
  • @Pascal 谢谢!一个大问题是我需要传递连接,所以如果 Hibernate 不能为我提供它的连接,那么它会很糟糕。我需要以其他方式获得这种联系。我认为任何有弃用连接方法的想法的人都应该三思而后行。
【解决方案3】:

connection() 刚刚在界面上被弃用。它仍然可以在SessionImpl 上找到。你可以做 Spring 所做的事情,然后调用它。

这是 Spring 3.1.1 中 HibernateJpaDialect 的代码

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 让你做的事情。很少有框架像 Hibernate 这样糟糕。
【解决方案4】:

还有另一个选项仍然涉及很多强制转换,但至少它不需要反射,这将使您返回编译时间检查:

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

您当然可以通过一些instanceof 检查使它变得“更漂亮”,但上面的版本对我有用。

【讨论】:

    【解决方案5】:
        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();
            }
        }
    

    【讨论】:

      【解决方案6】:

      试试这个

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

      实际上getSession返回的是Session接口类型,你应该看到会话的原始类是什么,类型转换为原始类然后获取连接。

      祝你好运!

      【讨论】:

      • ❤️ uuuuu 太令人沮丧了,这是必要的 - 尝试让我的应用程序设置为设置只读连接,以便在只读副本之间分发。谢谢。
      • 为什么没有更多的赞成票?有什么理由不应该这样做吗?非常适合我。
      • @tilper SessionImpl 在 Hibernate 的内部包中(因此不打算使用),这也是对实际实现的依赖。此外,当您投射会话时,您不能轻松地在测试中模拟会话。
      【解决方案7】:

      试试这个:

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

      【讨论】:

        【解决方案8】:

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

        【讨论】:

          【解决方案9】:

          这是在 Hibernate 4.3 中执行此操作的一种方法,它未被弃用:

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

          【讨论】:

          • session 转换为SessionImplementor 是否安全?
          • @DerekY,我知道这是旧的,但现在就处理它。是的,是的。所有的 Session 实现也是 SessionImplementor 的。
          【解决方案10】:

          这是我使用并为我工作的东西。 将 Session 对象向下转换为 SessionImpl 并轻松获取连接对象:

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

          session 是您的 Hibernate 会话对象的名称。

          【讨论】:

            【解决方案11】:

            我找到this article

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

            它帮助了我。

            【讨论】:

              【解决方案12】:

              使用Hibernate >= 5.0,您可以像这样获得Connection

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

              【讨论】:

                【解决方案13】:

                这是一个 Java 8 方法,用于返回 EntityManager 使用的 Connection,而无需实际对其进行任何操作:

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2011-06-23
                  • 2020-07-29
                  • 1970-01-01
                  • 2019-11-05
                  • 2010-10-08
                  • 2017-01-06
                  • 2014-02-12
                  • 2012-10-09
                  相关资源
                  最近更新 更多