如何解决JPA中@PersistenceContext注入EntityManager空指针异常问题
问题排查与修复步骤
- 优先修复Hibernate版本不一致问题
你当前项目中hibernate-jpamodelgen版本为4.3.9.Final,而hibernate-core、hibernate-entitymanager版本为4.3.7.Final,跨小版本的Hibernate组件混用会引发内部类调用空指针。请将所有Hibernate官方依赖的版本统一为4.3.7.Final。 - 修复
@PersistenceContext注入为null问题- 确认你的
JPAService是容器管理类:需要给类添加@Stateless(EJB)或者@ApplicationScoped/@RequestScoped(CDI)注解,自行通过new关键字实例化的类不会触发容器的资源注入逻辑。 - 修改
beans.xml配置:Java EE 7默认的Bean扫描规则为仅扫描带显式范围注解的类,你需要调整配置开启全量扫描,修改后的beans.xml内容如下:
<?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="all"> </beans> - 确认你的
- 修复ShrinkWrap打包冲突
你当前将所有Maven依赖都打入了测试War包,但是hibernate-core、hibernate-entitymanager的scope为provided,WildFly容器本身已经内置了这两个组件,你打包进去的版本和容器内置版本冲突会导致资源加载失败。修改依赖解析逻辑,排除provided范围的Hibernate相关依赖:
同时确认你WildFly嵌入式容器中已经配置了File[] mavenImports = Maven.resolver() .loadPomFromFile("pom.xml") .importRuntimeDependencies() .resolve() .withoutTransitivity() // 也可手动指定排除Hibernate相关provided依赖 .asFile();java:jboss/datasources/<dbName>对应的数据源,未配置的话可以临时将persistence.xml中的持久化单元改为RESOURCE_LOCAL类型,直接配置数据库连接参数用于测试。 - 修复手动创建
EntityManager空指针问题- 你当前的持久化单元默认是JTA事务类型,手动调用
Persistence.createEntityManagerFactory时没有容器提供JTA事务上下文,自然会初始化失败。如果要手动创建,需要修改persistence.xml的持久化单元配置:
<persistence-unit name="datasource" transaction-type="RESOURCE_LOCAL"> <!-- 移除jta-data-source配置,增加以下连接参数 --> <property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/> <property name="hibernate.connection.url" value="你的数据库连接地址"/> <property name="hibernate.connection.username" value="数据库用户名"/> <property name="hibernate.connection.password" value="数据库密码"/> </persistence-unit>- 你之前添加的拦截器配置语法错误,属性名和value之间缺少空格,导致配置不生效:
错误写法:<property name="hibernate.ejb.interceptor"value="org.<company>.utils.MyInterceptor"/>
正确写法:<property name="hibernate.ejb.interceptor" value="org.<company>.utils.MyInterceptor"/>
另外你不需要自行实现事务拦截器,容器会默认处理JTA事务的拦截逻辑。
- 你当前的持久化单元默认是JTA事务类型,手动调用
内容的提问来源于stack exchange,提问作者Tabs
相关产品推荐
相关产品推荐

