升级Spring Boot与Hibernate后单引号内{h-schema}无法解析求助
临时解决Hibernate 7.0.3中单引号内{h-schema}不解析的问题
升级到Spring Boot 3.5.3(对应Hibernate 7.0.3)后,原生SQL里单引号包裹的{h-schema}占位符确实会出现无法被替换的问题,目前可以用以下几种临时方案绕过:
方案一:直接从配置中读取schema名称拼接SQL
通过@Value注入配置好的默认schema,手动拼接到SQL语句中:
import org.springframework.beans.factory.annotation.Value; import jakarta.persistence.EntityManager; import org.springframework.stereotype.Repository; @Repository public class YourRepository { @Value("${spring.jpa.properties.hibernate.default_schema}") private String defaultSchema; private final EntityManager entityManager; public YourRepository(EntityManager entityManager) { this.entityManager = entityManager; } public Long getNextSeriesId() { String sql = String.format("SELECT nextval('%s.workflow_id')", defaultSchema); return Long.parseLong(String.valueOf(entityManager.createNativeQuery(sql).getSingleResult())); } }
方案二:通过Hibernate API动态获取schema名称
如果schema是动态变化的(比如多租户场景),可以通过SessionFactory获取当前生效的schema:
import jakarta.persistence.EntityManager; import org.hibernate.Session; import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.tool.schema.spi.SchemaNameResolver; import org.springframework.stereotype.Repository; @Repository public class YourRepository { private final EntityManager entityManager; public YourRepository(EntityManager entityManager) { this.entityManager = entityManager; } public Long getNextSeriesId() { Session session = entityManager.unwrap(Session.class); SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) session.getSessionFactory(); ServiceRegistryImplementor serviceRegistry = sessionFactory.getServiceRegistry(); SchemaNameResolver schemaNameResolver = serviceRegistry.getService(SchemaNameResolver.class); JdbcConnectionAccess jdbcConnectionAccess = session.getJdbcConnectionAccess(); String schema = schemaNameResolver.resolveSchemaName(jdbcConnectionAccess, sessionFactory.getSessionFactoryOptions()); String sql = String.format("SELECT nextval('%s.workflow_id')", schema); return Long.parseLong(String.valueOf(entityManager.createNativeQuery(sql).getSingleResult())); } }
方案三:检查引号策略配置
可以尝试调整Hibernate的标识符引号配置,在application.yml中添加:
spring: jpa: properties: hibernate: quote_identifiers: false quote_sql_identifiers: false
这个方案不一定能解决问题,但可以排除是引号策略干扰占位符解析逻辑的可能。
注:该问题大概率是Hibernate 7.x版本对原生SQL占位符解析逻辑的变更导致的,在官方补丁发布前,以上方案可作为临时替代。
内容的提问来源于stack exchange,提问作者Tim Malich
相关产品推荐
相关产品推荐

