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
- Enable global quotation mark configuration for Hibernate.
spring.jpa.properties.hibernate.globally_quoted_identifiers=true
- 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