明明是updateTime卻報:org.h2.jdbc.JdbcSQLSyntaxErrorException: Column "update_time" not found

背景

使用“Spring Boot With H2 Database”+“Spring Data JPA”寫的一個小東西,第一次用下h2和jpa,有幾個小問題,挑一個記錄下。

問題說明

1. 定義一個實體類,其中有一個更新時間屬性,定義如下:

2. 在數據庫表中定義這個字段:

3. 查詢sql:

4. 執行報錯:

其實,我整個代碼與sql腳本都沒有update_time字段,初用jpa,也沒仔細瞭解有什麼規範,我當時猜測,可能是我的代碼少了什麼映射配置,或者是框架層面自己給我轉換了。

分析

我看了下異常棧最近的有用的方法調用信息:

在源碼這裏:

這個columnLabel變量的值是update_time。

這裏出現問題的基本原因是,執行sql拿到結果集,期望從結果集取update_time列的過程中出問題了。問題是在columnLabelMap這裏,debug看了下這個變量的信息,根據經驗猜測應該是框架初始化過程中,對實體類相關字段作映射解析的時候轉換的時候發生的。

以前沒怎麼用過hibernate,比較好奇這個轉換的過程,所以小小研究了下,

於是根據調用棧從下往上翻了一下源碼及debug,花了幾十分鐘,終於找到了這個解析轉換的源碼位置:

先看下這代碼入口:在AnnotationBinder.java的bindClass方法上,關注點在persistenClass變量上,這裏將要處理爲類就是我定義的這個實體類

中間過程這裏不多說,接下來要處理實體類字段註解,會走到這裏:在AnnotationBinder.java類裏,會解析字段上的各種註解,

按我的配置是要走到這裏:Ejb3Column.java裏這個方法處

前面解析註解的時候,不論@Column註解是否存在並且定義的name是不是空,只要進入redefineColumnName方法,都會調用這段代碼:

如果沒有使用@Column註解指定,就是else上面使用的那個隱式命名:implicitName,都沒有區別,重要是這個命名策略的轉換過程,這個physicalNamingStrategy,這裏默認的是SpringPhysicalNamingStrategy,看下這個實現,我加上了註釋:

	@Override
	public Identifier toPhysicalColumnName(Identifier name,
			JdbcEnvironment jdbcEnvironment) {
		return apply(name, jdbcEnvironment);
	}

	private Identifier apply(Identifier name, JdbcEnvironment jdbcEnvironment) {
		if (name == null) {
			return null;
		}
		StringBuilder builder = new StringBuilder(name.getText().replace('.', '_'));
		for (int i = 1; i < builder.length() - 1; i++) {
            // 如果前一個字母是小寫,當前字母是大寫,後一個字母是小寫(駝峯命名)
            // 就在這個位置插入一個下劃線
			if (isUnderscoreRequired(builder.charAt(i - 1), builder.charAt(i),
					builder.charAt(i + 1))) {
				builder.insert(i++, '_');
			}
		}
        // 轉換小寫返回
		return getIdentifier(builder.toString(), name.isQuoted(), jdbcEnvironment);
	}

這就是轉換的地方,其實問題不大。

解決辦法

我簡單瀏覽下源碼包下的所有註解,發現好像沒看到哪個註解能達到我想要的效果。

必須承認我對這套東西用的少,不怎麼了解,感覺還是Mybatis以sql爲中心用着舒服,可能用慣了。

大致明白解析過程,其實有好幾個地方可以繞過去,比如查詢sql取個巧:

或者命名上不規範點,最終我覺得還是正常點,數據表定義規範點,這個字段改一下,改成update_time好了,圖省事。

後續有時間再翻下資料,瞭解下規範,找個正常點通用的方案。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章