升级Hibernate至5.0.12.Final时多Schema下Envers缺失revinfo表报错
这个问题我之前碰到过不少次,核心原因是Hibernate 5对Envers的多Schema支持逻辑做了关键调整:在Hibernate 4中,Envers只会绑定到你配置的默认Schema(也就是你的schema1),不会去其他Schema里找审计元数据表;但升级到5.0.x版本后,它会默认在所有被应用使用的Schema中尝试查找revinfo和*_aud这类审计表,而你的schema2压根没创建这些表,自然就抛出了找不到关系的错误。
下面给你几个可行的解决方案,按优先级推荐:
1. 给Envers明确指定专属Schema
这是最直接的方法,通过配置让Envers始终只在schema1中创建和查找审计表,完全不涉及schema2。
- 如果是用
persistence.xml或hibernate.cfg.xml配置:<property name="hibernate.envers.default_schema" value="schema1"/> - 如果是Spring Boot项目,在
application.properties/application.yml中添加:spring.jpa.properties.hibernate.envers.default_schema=schema1
这个配置会强制Envers把所有审计元数据都放在schema1下,不管你的实体属于哪个Schema,查询审计数据时也只会去schema1找,彻底避免它去schema2碰不存在的表。
2. 针对特定实体配置审计策略
如果schema2中的部分实体不需要审计,或者你想单独指定它们的审计表位置,可以通过实体注解来控制:
情况A:schema2的实体不需要审计
直接在实体类上添加@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED),告诉Envers不要为这个实体生成审计表,查询时也跳过审计检查:
@Entity @Table(schema = "schema2") @Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED) public class Schema2Entity { // 实体字段和方法 }
情况B:schema2的实体需要审计,但审计表放在schema1
用@AuditTable指定审计表的Schema和名称:
@Entity @Table(schema = "schema2") @Audited @AuditTable(schema = "schema1", value = "schema2_entity_aud") public class Schema2Entity { // 实体字段和方法 }
这样Envers会在schema1中创建schema2_entity_aud审计表,查询时也会去schema1读取审计数据,不会访问schema2。
3. 调整数据源默认Schema
如果你的应用大部分操作都围绕schema1,schema2只是用来同步数据的附属库,可以把数据源的默认Schema设置为schema1,然后访问schema2的表时通过@Table(schema="schema2")明确指定。这样Envers会默认使用数据源的默认Schema(schema1)来处理审计,不会主动去schema2查找审计表。
比如在数据源配置中(以Spring Boot为例):
spring.datasource.url=jdbc:postgresql://localhost:5432/your_db?currentSchema=schema1
验证方案
修改配置或代码后,重启应用,执行之前触发报错的业务操作,检查是否还会出现ERROR: relation "schema2.revinfo" does not exist的错误。如果报错消失,说明配置生效了。
内容的提问来源于stack exchange,提问作者Michael Hegner

