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

Java EE下Hibernate配置多H2持久化单元测试仅首个通过报Not an entity错误

问题根因

这个问题和H2是否支持多个内存数据库无关,你目前的用法本身是合法的——H2原生支持同JVM内创建多个命名不同的内存数据库,彼此完全隔离。你遇到的报错本质是批量测试时持久化上下文未隔离,具体原因有两个:

  1. 你第二个持久化单元CompanyPersistenceServiceBeanIntTest的配置中,仅注册了com.data.company.Company这一个实体类,且开了<exclude-unlisted-classes>true</exclude-unlisted-classes>,这个PU的元数据模型中本来就没有ItemHistory类的信息
  2. 批量运行测试时,前一个测试初始化的EntityManagerFactory/持久化上下文没有被销毁,或者第二个测试错误加载了不匹配的持久化单元,导致业务代码用到ItemHistory时,从当前加载的PU元数据中找不到对应实体定义,才抛出Not an entity错误

解决方案

按以下步骤排查修改即可解决:

  1. 确认每个测试类绑定了正确的持久化单元
    初始化EntityManagerFactory时必须显式指定对应PU的名称,不能依赖默认加载逻辑:

    • 对应ItemHistory相关测试:EntityManagerFactory emf = Persistence.createEntityManagerFactory("ItemHistoryPersistenceServiceBeanIntTest");
    • 对应Company相关测试:EntityManagerFactory emf = Persistence.createEntityManagerFactory("CompanyPersistenceServiceBeanIntTest");
      如果使用Spring/SpringBoot做测试,给每个测试类加上@DirtiesContext注解,强制测试跑完后销毁Spring上下文,避免上下文缓存复用前一个测试的持久化单元。
  2. 修复老版本Hibernate元数据共享问题
    你用的org.hibernate.ejb.HibernatePersistence是Hibernate 4.x及更早版本的提供器,该版本存在实体元数据全局缓存的bug,同一个类加载器下多个PU加载时会复用已扫描的实体元数据。给两个persistence-unit标签下都添加以下配置即可:

<shared-cache-mode>NONE</shared-cache-mode>

同时在properties中添加禁用元数据缓存的配置:

<property name="hibernate.ejb.metamodel.population" value="enabled"/>
  1. 修正hbm2ddl配置
    你已经通过JDBC URL的INIT参数指定了建表和插数的SQL脚本,完全不需要把hibernate.hbm2ddl.auto设为update,改为none即可完全复用你自定义的SQL脚本,稳定性更高。之前换其他值无法插数是因为create/create-drop配置会先清空表结构,覆盖你INIT脚本执行的结果。

补充说明

如果要实现测试跑完后自动销毁H2内存库,不需要依赖DB_CLOSE_DELAY参数,只需要在每个测试类的@After/@AfterEach方法中显式调用emf.close()关闭当前持久化单元的工厂即可,最后一个连接断开后H2会自动销毁对应内存库。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 21:48:03