一尘不染

从无状态Bean获取JDBC Connection对象

hibernate

在无状态会话Bean中,EntityManager注入了一个Connection对象,但是我想获得一个对象以调用DB过程。有什么解决办法吗?


阅读 311

收藏
2020-06-20

共1个答案

一尘不染

这将是JPA提供程序特定的代码。通常,这是通过unwrap()EntityManager类上调用来完成的。

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

JPA 2.0

entityManager.getTransaction().begin();
java.sql.Connection connection = entityManager.unwrap(java.sql.Connection.class); // unwraps the Connection class.
...
entityManager.getTransaction().commit();

JPA 1.0

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

注意,为JPA 2.0提供的解决方案将在Hibernate 3.6.5中失败,并带有一条PersistenceException消息

Hibernate无法解包接口java.sql.Connection

使用Skaffman提供的代码使它与Hibernate兼容(即使对于容器管理的持久性上下文,也已验证可在3.6.5下使用)。

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

2020-06-20