Spring Boot 2.7+Hibernate Envers插入审计版本时IDENTITY函数未找到
问题:Hibernate Envers插入审计版本时触发
call identity()报错 插入审计版本时出现如下错误日志:
Hibernate: insert into audited_revision (id, timestamp) values (default, ?) 2022-07-21 15:46:09.496 TRACE 67111 --- [ XNIO-1 task-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [TIMESTAMP] - [Thu Jul 21 15:46:09 CEST 2022] Hibernate: call identity() 2022-07-21 15:46:09.504 WARN 67111 --- [ XNIO-1 task-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 90022, SQLState: 90022 2022-07-21 15:46:09.504 ERROR 67111 --- [ XNIO-1 task-1] o.h.engine.jdbc.spi.SqlExceptionHelper : Function "IDENTITY" not found; SQL statement: call identity() [90022-214] 2022-07-21 15:46:09.518 ERROR 67111 --- [ XNIO-1 task-1] o.z.problem.spring.common.AdviceTraits : Internal Server Error org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [call identity()]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement
日志显示审计表已正确创建:
Hibernate: create table audited_revision (id bigint generated by default as identity, timestamp timestamp, primary key (id))
当前使用Spring Boot 2.7.2(对应Hibernate Core 5.6.9),相关application.yaml配置:
spring: jpa: defer-datasource-initialization: true database: H2 hibernate: ddl-auto: create-drop open-in-view: false properties: format_sql: true org: hibernate: envers: store_data_at_delete: true hibernate: temp: use_jdbc_metadata_defaults: false dialect: org.hibernate.dialect.H2Dialect show-sql: true
已知Hibernate相关问题在5.6.5版本已修复,但当前版本仍触发该错误,询问是Bug还是配置问题。
原因分析与解决方案
这大概率是配置问题,而非Hibernate的Bug,核心问题出在hibernate.temp.use_jdbc_metadata_defaults=false这个配置上:
- 当设置该参数为
false时,Hibernate会跳过从JDBC元数据中获取数据库特性的步骤,转而完全依赖配置的方言类提供数据库语法规则。 - 但
org.hibernate.dialect.H2Dialect在处理自增主键返回逻辑时,需要结合JDBC元数据判断H2的具体版本特性,关闭元数据读取后,Hibernate无法正确识别H2支持的主键返回语法,错误生成了过时的call identity()语句(H2实际支持直接调用IDENTITY()函数,而非call语法)。
修复步骤
- 优先方案:移除
hibernate.temp.use_jdbc_metadata_defaults=false配置(默认值为true),让Hibernate通过JDBC元数据自动适配H2的语法特性。 - 备选方案:如果必须关闭元数据读取,需指定与当前H2版本匹配的专用方言,比如
org.hibernate.dialect.H212107Dialect(根据你的H2版本选择对应子类),确保方言能正确输出H2兼容的主键返回语句。
同时确认H2数据库版本与Hibernate方言版本匹配,避免因版本不兼容导致的语法差异。
内容的提问来源于stack exchange,提问作者Appernicus
相关产品推荐
相关产品推荐

