1. 程式人生 > >Hibernate5中表欄位大小寫探討

Hibernate5中表欄位大小寫探討

        在實際應用中,遇到資料庫表中欄位名稱含大小寫的情況(如taskId,歷史遺留問題,不能修改資料庫),在使用Hibernate進行ORM時,遇到找不到欄位或資料庫新生成欄位問題。本篇以PostgreSQL 9.6資料庫和Hibernate 5.2.12.Final為例,探討Hibernate5中ORM時表字段大小寫敏感問題,並給出解決方案。

案例資料庫:

CREATE TABLE product
(
    pid character varying(32) NOT NULL,
    "taskId" character varying(32) NOT NULL,
    ...
    CONSTRAINT product_pkey PRIMARY KEY (pid)
)

        使用Spring Boot(1.5.4.RELEASE),Hibernate5進行表格ORM時,對taskId欄位的註解如下:
private String taskId;
@Column(name="taskId")
public String getTaskId() {
    return taskId;
}
public void setTaskId(String taskId) {
    this.taskId = taskId;
}

在命名策略spring.jpa.hibernate.naming.implicit-strategy和spring.jpa.hibernate.naming.physical-strategy不做任何配置,spring.jpa.hibernate.ddl-auto=update的情況下,啟動SpringBoot,資料庫表中生成欄位“task_id”,意味著Hibernate的ORM找不到資料庫表

taskId欄位,SpringBoot業務返回taskId值為null。

      當把@Column(name="taskId")改為@Column(name="taskid"),系統報錯,錯誤如下:

2017-11-01 19:24:41 ERROR o.h.e.jdbc.spi.SqlExceptionHelper - ERROR: column product0_.taskid does not exist
  建議:Perhaps you meant to reference the column "product0_.taskId" or the column "product0_.task_id".
  位置:86

顯然不能@Column(name="taskId")改為@Column(name="taskid"),回到@Column(name="taskId"),當在pgAdmin中執行SQL語句 “select taskId from product”時,報錯誤:

ERROR:  column "taskId" does not exist
LINE 1: select taskId from product
               ^
HINT:  Perhaps you meant to reference the column "product.taskId" or the column "product.task_id".
********** Error **********
        確實表字段taskId存在,是什麼原因呢,我們發現在建立含大寫字母的欄位名稱時,欄位名稱帶雙引號,改進SQL語句為“select 'taskId' from product”時,結果正確返回。接著,按照這個思路,改進@Column(name="taskId")為@Column(name="\"taskId\""),啟動程式,發現數據庫表還是新增了task_id欄位,SpringBoot業務返回taskId值為null。

        接下來SpringBoot新增命名策略:

spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

SpringBoot正確返回taskId值為資料庫中的值,同時,資料庫表沒有增加“task_id”欄位。

        另外,SpringNamingStrategy 在Hibernate5.1之後移除了,hibernate.ejb.naming_strategy將不再被支援,即spring.jpa.hibernate.naming-strategy的兩個可選值org.hibernate.cfg.ImprovedNamingStrategy和org.hibernate.cfg.DefaultNamingStrategy不起作用了,而是被替換成了兩個屬性:spring.jpa.hibernate.naming.implicit-strategy和spring.jpa.hibernate.naming.physical-strategy了。