Did Hibernate 6.4.4.Final parse the SQL in @ Formula incorrectly?

Basic environment

SpringBoot:3.2.4

spring-boot-starter-data-jpa:3.2.4

hibernate-core:6.4.4.Final

database:postgres or DM8

Problem description

  1. Enable global quotation mark configuration for Hibernate.
spring.jpa.properties.hibernate.globally_quoted_identifiers=true
  1. Annotate a field in the entity class with @ Formula and add quotation marks to the table name and field, keeping them lowercase.
@Formula("(SELECT m.\"info\" FROM \"message\" m WHERE m.\"id\" = id)")
private String info;

The SQL generated by Hibernate is as follows:

select u1_0."id",u1_0."age",u1_0."email",(SELECT m.u1_0."info" FROM u1_0."message" m WHERE m.u1_0."id" = u1_0.id),u1_0."name" from "user" u1_0

The correct SQL should be:

select u1_0."id",u1_0."age",u1_0."email",(SELECT m."info" FROM "message" m WHERE m."id" = u1_0.id),u1_0."name" from "user" u1_0;

Hibernate encountered an error parsing the SQL in @ Formula, where all fields or table names with quotation marks were concatenated with external aliases, resulting in an error in SQL execution.

The error info:

2026-01-15T22:20:13.404+08:00 ERROR 12576 --- [demo-springboot] [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.dao.InvalidDataAccessResourceUsageException: JDBC exception executing SQL [select u1_0."id",u1_0."age",u1_0."email",(SELECT m.u1_0."info" FROM u1_0."message" m WHERE m.u1_0."id" = u1_0.id),u1_0."name" from "user" u1_0] [ERROR: relation "u1_0.message" does not exist
  位置:69] [n/a]; SQL [n/a]] with root cause

org.postgresql.util.PSQLException: ERROR: relation "u1_0.message" does not exist
  位置:69
	at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2725) ~[postgresql-42.7.3.jar:42.7.3]
	at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2412) ~[postgresql-42.7.3.jar:42.7.3]
	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:371) ~[postgresql-42.7.3.jar:42.7.3]
	at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:502) ~[postgresql-42.7.3.jar:42.7.3]

core

sql


CREATE TABLE "public"."user" (
"id" BIGINT NOT NULL,
"name" VARCHAR(100) NULL,
"email" VARCHAR(100) NULL,
"age" NUMERIC NULL,
CONSTRAINT "user_pk" PRIMARY KEY ("id")
);

INSERT INTO "public"."user"
("id", "name", "email", "age")
VALUES(1, 'zhangsan', 'zhangsan@test.com', 18);
INSERT INTO "public"."user"
("id", "name", "email", "age")
VALUES(2, 'lisi', 'lisi@test.com', 19);
INSERT INTO "public"."user"
("id", "name", "email", "age")
VALUES(3, 'wangwu', 'wangwu@test.com', 20);



CREATE TABLE "public"."message" (
"id" BIGINT NOT NULL,
"info" VARCHAR NULL,
CONSTRAINT "message_pk" PRIMARY KEY ("id")
);

INSERT INTO "public"."message"
("id", "info")
VALUES(1, 'testtestetetetsttest');
INSERT INTO "public"."message"
("id", "info")
VALUES(2, 't2222222tetsttest');

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.4</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>17</java.version>
        <postgresql.driver.version>42.7.3</postgresql.driver.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>${postgresql.driver.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

controller

@RestController
@RequestMapping("/api/user")
public class UserController {
    @Autowired
    private UserRepository userRepository;

    @GetMapping
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
}

dao

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

}

user entity

import jakarta.persistence.*;
import lombok.Data;
import org.hibernate.annotations.Formula;

@Entity
@Data
@Table(name = "user")
public class User {
    @Id
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "email")
    private String email;

    @Column(name = "age")
    private Integer age;

//    @Formula("(SELECT m.info FROM message m WHERE m.id = id)")
    @Formula("(SELECT m.\"info\" FROM \"message\" m WHERE m.\"id\" = id)")
    private String info;
}

message entity

@Entity
@Data
@Table(name = "meaasge")
public class Message {
    @Id
    @Column(name = "id")
    private Long id;

    @Column(name = "info")
    private String info;
}

application.yml

spring:
  jpa:
    show-sql: "true"
    properties:
      hibernate:
        naming:
          physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
        globally_quoted_identifiers: true
      ddl-auto: "none"
    database-platform: "${SPRING_JPA_DATABASE_PLATFORM:org.hibernate.dialect.PostgreSQLDialect}"
  datasource:
    driverClassName: "${SPRING_DRIVER_CLASS_NAME:org.postgresql.Driver}"
    url: "${SPRING_DATASOURCE_URL:jdbc:postgresql://localhost:5432/test1}"
    username: "${SPRING_DATASOURCE_USERNAME:postgres}"
    password: "${SPRING_DATASOURCE_PASSWORD:postgres}"
logging:
  level:
    org.hibernate.orm.jdbc.bind: TRACE

Hi @Ten1, does the same happen if you don’t specify the globally_quoted_identifiers config property? And this the same formula expression work in previous Hibernate versions? If so, this might be a bug.

I would suggest trying to reproduce the issue with a supported Hibernate version and excluding Spring, you can use our test case templates for that. If you’re able to create a reproducer, please open an issue in our tracker.

The same problem still occurred when I did not specify the globally_quoted_identifiers config property.It can be executed normally without quotation marks, but my current database is case sensitive ,so quotation marks must be added to maintain lowercase.

Hi @mbladel I have reproduced the issue based on the test case templates and have initiated a pull request on GitHub. Please check.

Thank you for creating a reproducer, please open an issue in Hibernate’s Jira and link to your test case.