Wildfly下@PersistenceContext注入EntityManager失败的问题求助
你的问题核心在于CDI托管Bean与JPA容器EntityManager注入的交互冲突,结合Wildfly的Weld容器特性,下面详细拆解原因并给出针对性解决方案:
为什么会出现这个问题?
当你的项目中存在beans.xml且设置bean-discovery-mode="all"时,Wildfly的CDI子系统会把所有类(包括你的ConfigEntryDao)都当作CDI托管Bean。此时Weld会接管@PersistenceContext的注入逻辑,但如果你的persistence单元配置有细微问题,或者CDI与JPA子系统的初始化顺序不匹配,就会触发WFLYWELD0037错误——找不到指定的persistence单元。
而移除beans.xml后,CDI会默认使用annotated发现模式,只有带有CDI注解(如@Named、@ApplicationScoped)的类才会被托管。此时ConfigEntryDao不属于CDI Bean,JPA容器会直接处理@PersistenceContext注入,因此能找到PU,但代价是ConfigEntryDao无法被CDI注入到ConfigurationService中,导致后续CDI相关问题。
解决方案
方案1:调整beans.xml的Bean发现模式
将bean-discovery-mode="all"改为bean-discovery-mode="annotated",这样CDI只会托管带有明确CDI注解的类,ConfigEntryDao会交给JPA容器处理注入,同时保留beans.xml管理其他需要CDI的组件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" bean-discovery-mode="annotated"> </beans>
方案2:给ConfigEntryDao添加CDI作用域注解
如果你需要继续使用bean-discovery-mode="all",可以给ConfigEntryDao添加一个CDI作用域注解(如@ApplicationScoped或默认的@Dependent),让Weld能正确处理CDI Bean的@PersistenceContext注入:
@Transactional @ApplicationScoped public class ConfigEntryDao implements IDao<ConfigEntryEntity> { @PersistenceContext(unitName = XChangeUtil.JPA.JPA_PU_NAME) private EntityManager entityManager; // ....其他方法 }
方案3:验证persistence.xml的配置细节
确保你的persistence单元配置完全正确,这是基础前提:
- 确认
persistence.xml放在src/main/resources/META-INF目录下; - 检查persistence-unit的名称完全匹配
XChangeUtil.JPA.JPA_PU_NAME的值(Wildfly对PU名称大小写敏感); - 确保persistence-unit的
transaction-type设置为JTA(对应你使用的@Transactional注解),且数据源配置与Wildfly中配置的JTA数据源一致。
示例persistence.xml配置:
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="eclipselinkPu" transaction-type="JTA"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jta-data-source>java:jboss/datasources/YourJTADataSource</jta-data-source> <class>com.yourpackage.ConfigEntryEntity</class> <properties> <!-- 根据需要添加EclipseLink配置 --> <property name="eclipselink.logging.level" value="INFO"/> </properties> </persistence-unit> </persistence>
内容的提问来源于stack exchange,提问作者Tomas Bisciak

