You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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模式(推荐,适合生产环境)

  1. 删除persistence.xml里所有jakarta.persistence.jdbc.*属性
  2. 在应用服务器(如WildFly、Payara)中配置名为jdbc/file的JTA数据源,指向你的PostgreSQL数据库
  3. 保留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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 07:20:56