Java 从无状态Bean获取JDBC连接对象

Java 从无状态Bean获取JDBC连接对象,java,hibernate,jpa,jdbc,ejb,Java,Hibernate,Jpa,Jdbc,Ejb,在无状态会话Bean中,注入了EntityManager,但我希望获得连接对象,以便调用DB过程。 有什么解决方案吗?您必须使用entitymanager.getDelegate()或entitymanager.unwrap(这是更好的方法),将其转换为特定的实现(在Hibernate中称为会话)。然后可以调用connection()方法。请注意,这是不推荐的,请改用Work类。阅读更多信息。JPA API本身似乎没有提供这一点,这并不奇怪,但如果您愿意将代码与特定的实现相结合,那么您可以使用类

在无状态会话Bean中,注入了
EntityManager
,但我希望获得
连接
对象,以便调用DB过程。
有什么解决方案吗?

您必须使用
entitymanager.getDelegate()
entitymanager.unwrap
(这是更好的方法),将其转换为特定的实现(在
Hibernate
中称为
会话
)。然后可以调用
connection()
方法。请注意,这是不推荐的,请改用
Work
类。阅读更多信息。

JPA API本身似乎没有提供这一点,这并不奇怪,但如果您愿意将代码与特定的实现相结合,那么您可以使用类似的方法(Hibernate):


请注意,Hibernate 4中不推荐删除
Session.connection()
。考虑使用<代码> session .DOWORK()/<代码>。

< P>这将是JPA提供程序特定的代码。通常,这是通过调用
EntityManager
类来完成的

如果您使用的是EclipseLink,以下代码(来自)将非常有用(如果您使用的是应用程序管理的EntityManager):

JPA2.0

entityManager.getTransaction().begin();
java.sql.Connection connection = entityManager.unwrap(java.sql.Connection.class); // unwraps the Connection class.
...
entityManager.getTransaction().commit();
entityManager.getTransaction().begin();
UnitOfWork unitOfWork = (UnitOfWork)((JpaEntityManager)entityManager.getDelegate()).getActiveSession();
unitOfWork.beginEarlyTransaction();
Accessor accessor = unitOfWork.getAccessor();
accessor.incrementCallCount(unitOfWork.getParent());
accessor.decrementCallCount();
java.sql.Connection connection = accessor.getConnection();
...
entityManager.getTransaction().commit();
JPA1.0

entityManager.getTransaction().begin();
java.sql.Connection connection = entityManager.unwrap(java.sql.Connection.class); // unwraps the Connection class.
...
entityManager.getTransaction().commit();
entityManager.getTransaction().begin();
UnitOfWork unitOfWork = (UnitOfWork)((JpaEntityManager)entityManager.getDelegate()).getActiveSession();
unitOfWork.beginEarlyTransaction();
Accessor accessor = unitOfWork.getAccessor();
accessor.incrementCallCount(unitOfWork.getParent());
accessor.decrementCallCount();
java.sql.Connection connection = accessor.getConnection();
...
entityManager.getTransaction().commit();
注意,对于Hibernate 3.6.5,为JPA 2.0提供的解决方案将失败,并出现一个包含消息的
PersistenceException

Hibernate无法打开接口java.sql.Connection

使用Skaffman提供的代码使其能够在Hibernate下工作(即使在容器管理的持久性上下文中也可以在3.6.5下工作)


然而,EclipseLink wiki指出了一点有用的信息——如果您使用的是JTA管理的数据源,那么应该使用
@Resource
注释注入它,或者使用JNDI查找来检索它。只要您需要对数据库执行事务性工作,那么无论您是从数据源获得新连接还是从现有连接都无关紧要;大多数连接池都将提供与当前线程关联的相同连接(即实体管理器已经使用的连接)。因此,您可以避免以这种方式展开实体管理器,还可以对数据库执行事务活动;请记住,如果执行此操作,持久性上下文缓存和二级缓存可能不会同步。

在Hibernate中,skaffman发布的解决方案导致以下错误消息:

Hibernate无法打开类org.hsqldb.Session

我确实使用SessionImpl而不是Session使其工作:

Connection connection = entityManager().unwrap(SessionImpl.class).connection();
使用Session.doWork()解决此问题的示例如下:

private void executeNative(final String query) {
    Session session = entityManager.unwrap(Session.class);
    session.doWork(new Work() {

        @Override
        public void execute(Connection connection) throws SQLException {
            Statement s = null;
            try {
                s = connection.createStatement();
                s.executeUpdate(query);
            } 
            finally {
                if (s != null) {
                    s.close();
                }
            }
        }

    });
}

这非常有效,如果需要,您可以在其他地方使用连接对象

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

其中
session
是Hibernate会话对象的名称

下面是为我工作的代码。我们使用JPA1.0,Apache openjpa实现

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;

    }

}
在JPA2.0中,如果需要,JDBC是用于查询更多信息的nomodel或entity的por DTO 复杂的。有时候JPA不全是

我希望这将有助于您:

Statement statement = null;
EntityManager em = null;
em = emf.createEntityManager();
EntityTransaction et = em.getTransaction();

if(!et.isActive()) {
    et.begin();
}

java.sql.Connection connection = em.unwrap(java.sql.Connection.class);

    String qquerry="SELE ...
    try {   
        statement = connection.createStatement();
        ResultSet rs =  statement.executeQuery(qquerry);                                                              

        if (!rs.next()) {
            return null;
        }
        else{
            wwwwas=rs.getString(4);                                 
        }         
        statement.close();
        } 
    catch (SQLException e) {
        System.out.println("\n b-03:"+e);
        throw new RuntimeException(e.getMessage(), e);
    } 
    finally {
        try {
            //  em.getTransaction().commit();
            if(connection != null )
            connection.close();
        } 
        catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
       }
    }

JPAAPI不允许这样的事情,尽管JDOAPI允许.unwrap(java.sql.Connection.class)在OpenJPA(至少2.1.1)@Pawel中也不起作用,看起来是这样。谢谢!但是他们还没有发布2.2.0:)FWIW DataNucleus JPA似乎也支持JPA 2+展开可移植方法,因此只有Hibernate不支持。我确认EclipseLink的问题:如果在执行查询之前展开连接,将引发异常。如果在执行查询后展开连接,则展开将返回有效的java.sql.connection您应该将其强制转换为“org.hibernate.Session”,而不是“org.hsqldb.Session”