Java JSF项目JPA EntityManager为空报错的解决咨询
解决EntityManager为空的问题
核心原因是代码存在三个关键问题导致EntityManager注入失败,逐一解决即可:
1. 正确注入FileDAO,禁止手动实例化
你的FileManager类里的FileDAO未通过容器注入。由于FileDAO是@Stateless EJB,必须由容器管理才能触发@PersistenceContext的注入,手动实例化会导致容器无法处理注解,最终em始终为null。
修改FileManager:
import dao.FileDAO; import entity.Filee; import jakarta.enterprise.context.SessionScoped; import jakarta.inject.Named; import jakarta.inject.Inject; import jakarta.servlet.http.Part; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.nio.file.Files; import java.util.List; @Named @SessionScoped public class FileManager implements Serializable{ private Filee file; @Inject private FileDAO fdao; private List<Filee> list; private Part doc; private String uploadTo="C:\\files\\"; public void upload() { try { InputStream input = doc.getInputStream(); File f = new File(uploadTo + doc.getSubmittedFileName()); Files.copy(input, f.toPath()); Filee newFile = new Filee(); newFile.setPath(f.getParent()); newFile.setName(f.getName()); newFile.setType(doc.getContentType()); getFdao().create(newFile); } catch (IOException e) { System.out.println(e.getMessage()); } } public FileDAO getFdao() { return fdao; } }
2. 统一JPA包名,适配Jakarta EE 3.0
你的persistence.xml使用Jakarta Persistence 3.0,但代码混用了javax.persistence和jakarta.persistence包,容器无法识别旧的javax注解,导致@PersistenceContext不生效。
修改AbstractFacade:
将所有javax.persistence替换为jakarta.persistence:
import java.io.Serializable; import jakarta.persistence.EntityManager; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.Root; import jakarta.persistence.Query; import java.util.List; public abstract class AbstractFacade<T> implements Serializable{ private Class<T> entityClass; public AbstractFacade(Class<T> entityClass) { this.entityClass = entityClass; } protected abstract EntityManager getEntityManager(); public void create(T entity) { getEntityManager().persist(entity); } public void edit(T entity) { getEntityManager().merge(entity); } public void remove(T entity) { getEntityManager().remove(getEntityManager().merge(entity)); } public T find(Object id) { return getEntityManager().find(entityClass, id); } public List<T> findAll() { CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(); cq.select(cq.from(entityClass)); return getEntityManager().createQuery(cq).getResultList(); } public List<T> findRange(int[] range) { CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(); cq.select(cq.from(entityClass)); Query q = getEntityManager().createQuery(cq); q.setMaxResults(range[1] - range[0] + 1); q.setFirstResult(range[0]); return q.getResultList(); } public int count() { CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(); Root<T> rt = cq.from(entityClass); cq.select(getEntityManager().getCriteriaBuilder().count(rt)); Query q = getEntityManager().createQuery(cq); return ((Long) q.getSingleResult()).intValue(); } }
修改FileDAO:
同样替换包名:
import entity.Filee; import jakarta.ejb.Stateless; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; @Stateless public class FileDAO extends AbstractFacade<Filee> { @PersistenceContext(unitName = "filePU") private EntityManager em; public FileDAO() { super(Filee.class); } @Override protected EntityManager getEntityManager() { return em; } }
3. 修正persistence.xml配置
你的persistence-unit使用JTA事务类型,但同时配置了jdbc属性,二者冲突:JTA模式下应使用服务器配置的数据源,而非直接写jdbc参数。
选项A:继续用JTA模式(推荐,适合生产环境)
- 删除persistence.xml里所有
jakarta.persistence.jdbc.*属性 - 在应用服务器(如WildFly、Payara)中配置名为
jdbc/file的JTA数据源,指向你的PostgreSQL数据库 - 保留
transaction-type="JTA"和<jta-data-source>jdbc/file</jta-data-source>
修改后的persistence.xml:
<?xml version="1.0" encoding="UTF-8"?> <persistence version="3.0" xmlns="https://jakarta.ee/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"> <persistence-unit name="filePU" transaction-type="JTA"> <jta-data-source>jdbc/file</jta-data-source> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <property name="jakarta.persistence.schema-generation.database.action" value="create"/> </properties> </persistence-unit> </persistence>
选项B:改用RESOURCE_LOCAL模式(适合快速测试)
若不想配置服务器数据源,可改为本地事务模式,保留jdbc参数并修改transaction-type:
<?xml version="1.0" encoding="UTF-8"?> <persistence version="3.0" xmlns="https://jakarta.ee/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"> <persistence-unit name="filePU" transaction-type="RESOURCE_LOCAL"> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <property name="jakarta.persistence.schema-generation.database.action" value="create"/> <property name="jakarta.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/file"/> <property name="jakarta.persistence.jdbc.user" value="postgres"/> <property name="jakarta.persistence.jdbc.password" value="12345"/> <property name="jakarta.persistence.jdbc.driver" value="org.postgresql.Driver"/> </properties> </persistence-unit> </persistence>
注意:RESOURCE_LOCAL模式需手动管理事务,需修改AbstractFacade的create/edit/remove方法,添加事务控制逻辑:
public void create(T entity) { EntityManager em = getEntityManager(); try { em.getTransaction().begin(); em.persist(entity); em.getTransaction().commit(); } catch (Exception e) { if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } throw new RuntimeException(e); } }
最后检查依赖
确保项目依赖正确的Jakarta EE API,例如Maven的pom.xml添加:
<dependency> <groupId>jakarta.persistence</groupId> <artifactId>jakarta.persistence-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jakarta.ejb</groupId> <artifactId>jakarta.ejb-api</artifactId> <version>4.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.6.0</version> </dependency>
完成以上修改后重新部署项目,EntityManager即可正常注入。
内容的提问来源于stack exchange,提问作者demirs
相关产品推荐
相关产品推荐

