且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-12-03 16:01:04

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

This is going to be JPA provider specific code. Typically this is done by invoking unwrap() on the EntityManager class.

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

If you are using EclipseLink, the following code (from the EclipseLink wiki) will be useful (in the case you are using an application-managed 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

Note, that the solution provided for JPA 2.0 will fail for Hibernate 3.6.5 with a PersistenceException containing the message

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

Hibernate cannot unwrap interface java.sql.Connection

使用 Skaffman 提供的代码让它在 Hibernate 上工作(即使对于容器管理的持久性上下文,也验证了它在 3.6.5 下工作).

Use the code provided by Skaffman to get it to work against Hibernate (verified to work under 3.6.5 even for container managed persistence contexts).

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

However, the EclipseLink wiki points out one useful bit of info - if you are using JTA managed datasources, you should be injecting it using the @Resource annotation or retrieving it using a JNDI lookup. As long as you need to perform transactional work against the database, it is immaterial as to whether you are obtaining a new connection from the data source or an existing one; most connection pools will anyway provide the same connection that is associated with the current thread (i.e. the one already used by the entity manager). You would therefore avoiding unwrapping the entity manager this way, and also perform transactional activity against the database; do remember that the persistence context cache, and a second-level cache may not be synchronized if you do this.