Quarkus中使用Hibernate跨数据库关联表报未找到@Entity实体错误
问题根因
- 配置文件中第二个数据源及对应Hibernate持久化单元(PU)的配置全部被注释,同时未给默认主PU指定实体扫描包路径,导致命名为database02的PU初始化时扫描不到任何实体,直接抛出
java.lang.IllegalStateException: No entities were found异常。 - 跨库JPA关联写法不成立:JPA的
@OneToOne这类关联映射仅能在同一个持久化单元(即同一个数据库连接上下文)内生效。两个独立数据源对应独立的PU、独立的数据库会话,Hibernate无法自动完成跨PU的关联查询、级联操作,哪怕两个库属于同一个MySQL实例也不支持。 - 主PU默认会扫描全项目所有标注
@Entity的类,会把属于database02的Address实体也纳入管理,但主PU连接的是database01,库中不存在address表,会进一步引发启动时的表映射校验错误。 - 依赖存在版本冲突:当前
quarkus-hibernate-validator使用8.0.0.Alpha3版本,和其余Quarkus组件的2.10.0.Final版本不匹配,容易触发类加载异常。
修复步骤
- 放开第二个数据源的配置注释,同时为两个持久化单元明确指定实体扫描包路径,避免跨包扫描冲突,修正后的配置如下:
# 主数据源 对应database01 quarkus.datasource.db-kind = mysql quarkus.datasource.username = root quarkus.datasource.password = quarkus.datasource.jdbc.url = jdbc:mysql://localhost:3306/database01?useSSL=false&autoreconnect=true&zeroDateTimeBehavior=convertToNull # 主PU指定仅扫描database01的实体包 quarkus.hibernate-orm.packages=wsi.model.entity.database01 # 第二个数据源 对应database02 quarkus.datasource."database02".db-kind = mysql quarkus.datasource."database02".username = root quarkus.datasource."database02".password = quarkus.datasource."database02".jdbc.url = jdbc:mysql://localhost:3306/database02?useSSL=false&autoreconnect=true&zeroDateTimeBehavior=convertToNull quarkus.hibernate-orm."database02".datasource=database02 # 第二个PU指定仅扫描database02的实体包 quarkus.hibernate-orm."database02".packages=wsi.model.entity.database02 # 开启第二个PU的Panache支持,否则Panache无法识别该PU下的实体 quarkus.hibernate-orm."database02".panache.enabled=true
- 移除Users实体中跨库的
@OneToOne关联映射。跨库场景下JPA不支持原生关联,需要将关联字段改为普通基础类型存储address_id,查询时在业务代码层手动组装两个数据源的查询结果,修正后的Users实体如下:
package wsi.model.entity.database01; import javax.persistence.*; @Entity @Table(schema = "database01", name = "users") @Cacheable public class Users { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private int id; // 移除跨库@OneToOne关联,直接存储关联ID @Column(name = "address_id") private Integer addressId; public int getId() { return id; } public void setId(int id) { this.id = id; } public Integer getAddressId() { return addressId; } public void setAddressId(Integer addressId) { this.addressId = addressId; } }
- 修正依赖版本,将
quarkus-hibernate-validator的版本和其余Quarkus组件对齐,去掉单独指定的版本号,直接使用Quarkus平台引入的稳定版本即可,避免类冲突。
额外说明
- 不要指望通过
@Table注解的schema参数实现跨库关联,只要配置了独立数据源,Hibernate就会将其识别为完全独立的库,不会自动执行跨库join。如果确实需要单SQL完成跨库查询,不要配置多数据源,只用一个账号授予两个库的访问权限,单数据源连接到MySQL实例,通过库名.表名的方式写SQL即可,这种场景下可以保留实体关联映射,也就是你之前两表同库时能正常运行的逻辑。 - 如果使用Panache Repository模式,需要在Repository类上通过
@PersistenceUnit注解指定对应的持久化单元名称,避免默认绑定主PU找不到对应实体。
内容的提问来源于stack exchange,提问作者user15187942
相关产品推荐
相关产品推荐

