代码之家  ›  专栏  ›  技术社区  ›  Jay

在纯JPA设置中获取数据库连接

  •  54
  • Jay  · 技术社区  · 15 年前

    12 回复  |  直到 15 年前
        1
  •  54
  •   Pascal Thivent    15 年前

    Session EntityManager . 使用JPA 1.0,您必须执行以下操作:

    Session session = (Session)em.getDelegate();
    Connection conn = session.connection();
    

    请注意 getDelegate() 是不可移植的,这个方法的结果是特定于实现的:上面的代码在JBoss中工作,对于GlassFish,您必须对其进行调整—看一下 Be careful while using EntityManager.getDelegate() .

    Connection conn = em.unwrap(Session.class).connection();
    

    如果在容器内运行,还可以对配置的 DataSource .

        2
  •  59
  •   Sarath Chandra    9 年前

    根据 hibernate 文件 here ,

    . (计划在4.x中删除)。根据需要更换;直接使用JDBC 嫁妆(org.hibernate.jdbc.Work) ...

    Session session = entityManager.unwrap(Session.class);
    session.doWork(new Work() {
    
        @Override
        public void execute(Connection connection) throws SQLException {
            // do whatever you need to do with the connection
        }
    });
    
        3
  •  31
  •   animuson    14 年前

    如果您使用的是JAVA EE 5.0,那么最好的方法是使用@Resource注释将数据源注入类(例如EJB)的属性中,以保存遗留报告工具的数据源资源(例如Oracle数据源),方法如下:

    @Resource(mappedName="jdbc:/OracleDefaultDS") DataSource datasource;
    

    稍后,您可以通过以下方式获取连接,并将其传递给遗留报告工具:

    Connection conn = dataSource.getConnection();
    
        4
  •  27
  •   armando    12 年前

    如果使用EclipseLink:

    entityManager.getTransaction().begin();
    java.sql.Connection connection = entityManager.unwrap(java.sql.Connection.class);
    ...
    entityManager.getTransaction().commit();
    
        5
  •  15
  •   Sasha Shpota A-Bag    6 年前

    :

    Session session = entityManager.unwrap(Session.class);
    session.doWork(connection -> doSomeStuffWith(connection));
    
        6
  •  14
  •   petertc    12 年前

    由于@Pascal建议的代码已被@Jacob否决,我发现 this another way

    import org.hibernate.classic.Session;
    import org.hibernate.connection.ConnectionProvider;
    import org.hibernate.engine.SessionFactoryImplementor;
    
    Session session = (Session) em.getDelegate();
    SessionFactoryImplementor sfi = (SessionFactoryImplementor) session.getSessionFactory();
    ConnectionProvider cp = sfi.getConnectionProvider();
    Connection connection = cp.getConnection();
    
        7
  •  9
  •   Jin Kwon    6 年前

    这个词 冬眠 .

    日蚀

    • EntityManager 必须连接到 Transaction 或者 unwrap null
    • 我不确定关闭连接的责任。
    // --------------------------------------------------------- EclipseLink
    try {
        final Connection connection = manager.unwrap(Connection.class);
        if (connection != null) { // manage is not in any transaction
            return function.apply(connection);
        }
    } catch (final PersistenceException pe) {
        logger.log(FINE, pe, () -> "failed to unwrap as a connection");
    }
    

    冬眠

    // using vendor specific APIs
    final Session session = (Session) manager.unwrap(Session.class);
    //return session.doReturningWork<R>(function::apply);
    return session.doReturningWork(new ReturningWork<R>() {
        @Override public R execute(final Connection connection) {
            return function.apply(connection);
        }
    });
    

    嗯,我们(至少我)可能不需要任何特定于供应商的依赖关系。 Proxy

    try {
        // See? You shouldn't fire me, ass hole!!!
        final Class<?> sessionClass
                = Class.forName("org.hibernate.Session");
        final Object session = manager.unwrap(sessionClass);
        final Class<?> returningWorkClass
                = Class.forName("org.hibernate.jdbc.ReturningWork");
        final Method executeMethod
                = returningWorkClass.getMethod("execute", Connection.class);
        final Object workProxy = Proxy.newProxyInstance(
                lookup().lookupClass().getClassLoader(),
                new Class[]{returningWorkClass},
                (proxy, method, args) -> {
                    if (method.equals(executeMethod)) {
                        final Connection connection = (Connection) args[0];
                        return function.apply(connection);
                    }
                    return null;
                });
        final Method doReturningWorkMethod = sessionClass.getMethod(
                "doReturningWork", returningWorkClass);
        return (R) doReturningWorkMethod.invoke(session, workProxy);
    } catch (final ReflectiveOperationException roe) {
        logger.log(Level.FINE, roe, () -> "failed to work with hibernate");
    }
    

    OpenJPA公司

    我不确定OpenJPA是否已经提供了一种使用 unwrap(Connection.class)

    不清楚关闭连接的责任。文件(上面的链接之一)似乎说得很清楚,但我不擅长英语。

    try {
        final Class<?> k = Class.forName(
                "org.apache.openjpa.persistence.OpenJPAEntityManager");
        if (k.isInstance(manager)) {
            final Method m = k.getMethod("getConnection");
            try {
                try (Connection c = (Connection) m.invoke(manager)) {
                    return function.apply(c);
                }
            } catch (final SQLException sqle) {
                logger.log(FINE, sqle, () -> "failed to work with openjpa");
            }
        }
    } catch (final ReflectiveOperationException roe) {
        logger.log(Level.FINE, roe, () -> "failed to work with openjpa");
    }
    
        8
  •  2
  •   Kees de Kooter chotai.mit    15 年前

    Hibernate在内部使用ConnectionProvider来获取连接。从hibernate javadoc:

    ConnectionProvider接口不打算向应用程序公开。相反,Hibernate在内部使用它来获取连接。

        9
  •  1
  •   Aneesh Vijendran    14 年前

    我今天遇到了这个问题,这就是我的窍门,对我很有效:

       EntityManagerFactory emf = Persistence.createEntityManagerFactory("DAOMANAGER");
       EntityManagerem = emf.createEntityManager();
    
       org.hibernate.Session session = ((EntityManagerImpl) em).getSession();
       java.sql.Connection connectionObj = session.connection();
    

    虽然不是最好的方法,但它确实起到了作用。

        10
  •  1
  •   aborskiy    10 年前

    import java.sql.Connection;
    import org.apache.openjpa.persistence.OpenJPAEntityManager;
    import org.apache.openjpa.persistence.OpenJPAPersistence;
    
    public final class MsSqlDaoFactory {
    
    
           public static final Connection getConnection(final EntityManager entityManager) {
                  OpenJPAEntityManager openJPAEntityManager = OpenJPAPersistence.cast(entityManager);
                  Connection connection = (Connection) openJPAEntityManager.getConnection();
                  return connection;
    
            }
    
    }
    
        11
  •  1
  •   Dherik    8 年前

    我使用的是Hibernate的旧版本(3.3.0)和OpenEJB的最新版本(4.6.0)。我的解决方案是:

    EntityManagerImpl entityManager = (EntityManagerImpl)em.getDelegate();
    Session session = entityManager.getSession();
    Connection connection = session.connection();
    Statement statement = null;
    try {
        statement = connection.createStatement();
        statement.execute(sql);
        connection.commit();
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
    

    Commit can not be set while enrolled in a transaction
    

    因为上面的代码在EJB控制器中(您不能 commit 在交易中)。我用 @TransactionAttribute(value = TransactionAttributeType.NOT_SUPPORTED) 问题消失了。

        12
  •  0
  •   uvperez    10 年前

    Connection getConnection() {
        Session session = entityManager.unwrap(Session.class);
        MyWork myWork = new MyWork();
        session.doWork(myWork);
        return myWork.getConnection();
    }
    
    private static class MyWork implements Work {
    
        Connection conn;
    
        @Override
        public void execute(Connection arg0) throws SQLException {
            this.conn = arg0;
        }
    
        Connection getConnection() {
            return conn;
        }
    
    }