为什么 EntityManager 的 getDelegate() 方法不 return EntityManagerImpl 作为 Hibernate 中的底层对象?

Why EntityManager's getDelegate() method does not return EntityManagerImpl as underlying object in Hibernate?

我正在将应用程序从 Hibernate/OpenEJB/TomEE 迁移到 Hibernate/JBoss,我在运行时遇到此异常:

java.lang.ClassCastException: org.hibernate.internal.SessionImpl cannot be cast to org.hibernate.ejb.EntityManagerImpl

虽然 运行 此代码:

...
import javax.persistence.EntityManager;
...
@PersistenceContext(...)
protected EntityManager em;
...
EntityManagerImpl hibernateEntityManagerImpl = (EntityManagerImpl)em.getDelegate();
Session sess = hibernateEntityManagerImpl.getSession();
...

相同的代码在 TomEE 中运行。我不知道为什么 getDelegate() 方法没有 return EntityManager 作为底层对象。

注意:

感谢您的帮助。

请注意,getDelegate 方法实现是特定于提供者的。适用于一个提供者的方法不一定适用于另一个 jpa 提供者。 这是 javadoc 对 getDelegate()

的描述

Return the underlying provider object for the EntityManager, if available. The result of this method is implementation specific.

JPA 规范告诉提供者什么是强制性的,什么不是。 "Not Mandatory" jpa 规范中的内容将由 jpa 提供程序实现或不实现。

最好只使用 JPA 中的强制规范,因为我们的目标是减少提供程序对 JPA 的依赖。我们不应该使用提供者特定的实现。

如果您正在使用 JBoss EAP/Hibernate,您可以替换

EntityManagerImpl hibernateEntityManagerImpl = (EntityManagerImpl)em.getDelegate();

作者:

org.hibernate.Session sess = (Session) em.getDelegate();

您没有说明您使用的 JBoss EAP 是哪个版本,所以我认为它是最新的。

JBoss EAP / JBoss AS / WildFly 捆绑了它自己的 JBoss Hibernate。如果您的应用程序中捆绑了另一个 Hibernate 库,它可能会或可能不会被您的应用程序的类加载器使用,具体取决于类加载配置。

如果您的应用程序是基于 Maven 的,您应该遵循 JBoss 开发人员指南。检查 JBoss Quickstarts 并相应地修改你的 pom。这真的很值得,会为你省去很多麻烦。

最后,尽量避免使用专有 API。每次您重新键入特定实现的某些接口时,您可能会使用专有的 API 并自找麻烦。