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

JPA报InaccessibleObjectException无法访问实体私有字段问题

问题根因

你的判断完全准确,报错是Java模块系统(JPMS)的反射权限配置缺失导致的。
核心报错信息已经明确指出问题:

java.lang.reflect.InaccessibleObjectException: Unable to make field private int com.c57lee.possystemdemo.obj.Test.testId accessible: module com.c57lee.possystemdemo does not "opens com.c57lee.possystemdemo.obj" to unnamed module @191c1c44

Hibernate通过反射读取实体类私有字段完成ORM映射,Java 9+启用模块系统后,默认禁止外部模块反射访问未开放包下的类成员。你当前的module-info.java仅开放了根包给JavaFX FXML模块,既没开放实体类所在的com.c57lee.possystemdemo.obj包,也缺少Hibernate相关的依赖声明。

除此之外你还有几处配置问题:

  • persistence.xml使用的2.1版本是旧JPA(javax包)规范,和你当前引入的Jakarta Persistence 3.0、Hibernate 6不兼容
  • 没有在持久化配置中声明受管理的实体类,Hibernate无法扫描到Test实体
  • JDBC连接URL缺少MySQL 8.x驱动必需的时区、SSL相关参数,后续连通数据库时也会触发报错

修复步骤

1. 修改module-info.java配置

补全Hibernate依赖声明,同时把实体类所在包开放给Hibernate反射访问权限,修改后内容如下:

module com.c57lee.possystemdemo {
    requires javafx.controls;
    requires javafx.fxml;
    requires java.sql;
    requires jakarta.persistence;
    // 引入Hibernate核心模块
    requires org.hibernate.orm.core;

    opens com.c57lee.possystemdemo to javafx.fxml;
    // 开放实体类所在包给Hibernate、JPA模块,允许反射访问私有成员
    opens com.c57lee.possystemdemo.obj to org.hibernate.orm.core, jakarta.persistence;
    
    exports com.c57lee.possystemdemo;
}

后续新增其他存放实体类的包,都要按同样格式添加opens声明,否则Hibernate访问对应实体时还会报同类错误。

2. 修正persistence.xml配置

升级持久化规范版本到3.0适配Jakarta EE,添加实体类声明,补全JDBC连接参数,修改后内容如下:

<?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="c57leePersistence"  transaction-type="RESOURCE_LOCAL">
        <!-- 声明所有受JPA管理的实体类 -->
        <class>com.c57lee.possystemdemo.obj.Test</class>
        
        <properties>
            <property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver" />
            <property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/POSSystemDemo?useSSL=false&amp;serverTimezone=UTC&amp;allowPublicKeyRetrieval=true" />
            <property name="jakarta.persistence.jdbc.user" value="root" />
            <property name="jakarta.persistence.jdbc.password" value="" />
            <!-- 开发阶段可选配置:自动建表、打印SQL方便调试 -->
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>
</persistence>

后续新增实体类,要在<persistence-unit>标签下添加对应的<class>标签声明。如果你的数据库设置了密码,把jakarta.persistence.jdbc.password的值改成对应密码即可。

3. 补充资源释放逻辑(建议优化)

你当前的代码用完EntityManager、EntityManagerFactory后没有关闭,长期运行会出现连接泄漏,建议调整JPA操作代码,异常时回滚事务,用完主动释放资源:

@Override
public void start(Stage stage) throws IOException {
    EntityManagerFactory emf = null;
    EntityManager em = null;
    try {
        emf = Persistence.createEntityManagerFactory("c57leePersistence");
        em = emf.createEntityManager();
        em.getTransaction().begin();

        Test test1 = new Test();
        test1.setTestId(1);
        test1.setTestName("testname");
        test1.setTestScore(70);
        System.out.println(test1);
        em.persist(test1);
        em.getTransaction().commit();
    } catch (Exception e) {
        if (em != null && em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }
        e.printStackTrace();
    } finally {
        if (em != null) em.close();
        if (emf != null) emf.close();
    }

    // 原有JavaFX界面加载逻辑写在此处
}

改完以上配置重新编译运行,反射访问报错就会消失,JPA可以正常完成实体持久化操作。

内容的提问来源于stack exchange,提问作者lcm5506

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 05:03:15