Wildfly 10.x中Eclipselink保存对象触发NullPointerException问题
我来帮你搞定这个切换持久化框架后遇到的麻烦。你碰到的NullPointerException出现在org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.checkForUnregisteredExistingObject方法里,大概率是Wildfly自带的Hibernate和你打包的Eclipselink之间的类加载冲突导致的——毕竟Wildfly默认把Hibernate作为JPA的默认实现,就算你换了Eclipselink,容器可能还是优先加载Hibernate的类,或者依赖版本不匹配。
另外看你的POM配置,你导入了JBoss EAP的Java EE7 BOM,这个BOM默认会引入Hibernate相关依赖,而且你没有明确指定Eclipselink的版本和依赖范围,这也会加剧冲突。
具体解决方案
1. 修正Maven依赖配置
首先得把Eclipselink的依赖配置对,还要排除BOM里自带的Hibernate相关依赖:
<dependencies> <!-- 你原来的JSF、CDI这些provided依赖可以保留 --> <!-- 引入Eclipselink,选和Java EE7兼容的版本,比如2.6.x系列 --> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>eclipselink</artifactId> <version>2.6.4</version> <scope>compile</scope> <!-- Wildfly默认不带Eclipselink,所以打包进应用 --> </dependency> <!-- 排除JBoss BOM里的Hibernate实现,只保留JPA API --> <dependency> <groupId>org.jboss.spec.javax.persistence</groupId> <artifactId>jboss-jpa-api_2.1_spec</artifactId> <scope>provided</scope> <exclusions> <exclusion> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> </exclusion> <exclusion> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
2. 告诉Wildfly别用自带的Hibernate
在你的WAR包的WEB-INF目录下新建jboss-deployment-structure.xml,明确让容器排除Hibernate模块,使用你自己的Eclipselink:
<?xml version="1.0" encoding="UTF-8"?> <jboss-deployment-structure> <deployment> <!-- 排除Wildfly自带的Hibernate相关模块 --> <exclusions> <module name="org.hibernate" /> <module name="org.hibernate.jpa" /> </exclusions> <!-- 确保JPA API模块可用 --> <dependencies> <module name="javax.persistence.api" export="true" /> </dependencies> </deployment> </jboss-deployment-structure>
3. 确认persistence.xml配置正确
一定要在persistence.xml里明确指定Eclipselink作为持久化提供者,别让容器自己猜:
<persistence-unit name="YourPersistenceUnitName" transaction-type="JTA"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <!-- 你的数据源配置、实体类扫描等 --> <properties> <!-- 可以加一些Eclipselink的调试属性,方便排查问题 --> <property name="eclipselink.logging.level" value="FINE"/> <property name="eclipselink.ddl-generation" value="create-or-extend-tables"/> </properties> </persistence-unit>
4. 检查代码里的小问题
另外,那个NPE也有可能是你要保存的对象有未初始化的关联对象,或者在调用EntityManager.persist()之前错误设置了ID字段(比如用自动生成ID的策略时手动给ID设了值?不过这个概率小,先解决类加载冲突再看)。
验证步骤
- 先清理Maven缓存,重新构建项目:
mvn clean install - 部署到Wildfly后,看看服务器日志里有没有类加载相关的警告
- 再尝试保存对象,应该就不会再出那个NPE了
内容的提问来源于stack exchange,提问作者user9764386

