現象
更新money字段的值sql,卻報too long for column "type",其實更新語句不涉及type字段,但問題在這裏。
有遇到類似問題的,接下來對號入座。
出現這這個問題,有以下幾種情形:
1. java定義type字段是int類型
2. db中這個字段是enum類型
3. 插入和查詢時這個字段是沒有問題的
4. 更新這個字段沒有問題
5. 更新別的字段的同時沒有更新這個字段,就出問題了,如果更新過這個字段問題解決,下次重啓,問題復現
6. 用的h2數據庫
原因
翻了下出問題異常堆棧的時候,在一個方法上看到這個註釋:
這裏可以看出,即使更新一個字段也會處理所有列。。。雖然更新的時候沒有這個字段,依然會處理下。
拋異常的地方在這裏:value是int類型,value的precision的值是10,參數precision的值是7(應該是按‘complex'的長度計算的,即enum的最大字段的長度)。這裏判斷value的precision過大,不合法,就異常了。
而type列的值是0或1,一個整數類型。在後面有個精度計算判斷的時候,int的爲10,而這個enum類型的type列的精度爲7,不合法了。就拋這個異常了。
出現type列爲Int類型的原因看下圖,在Page.read(buff, pos, map)方法內,後面有很多操作,就不一一截圖了。我花了大晚上時間翻這塊代碼,搞清楚它這個反序列化過程(先key,然後是values,在處理values時把一行的每一個列依次反序列化,buff裏保存了很多信息比如類型,值什麼的,有它自己的編解碼方式)。在初始化的時候計算的這個type column的信息就是enum,但是這裏反序列化出來的類型信息,如果是enum或int都按int處理,返回的就是值的角標。
這是h2自己加載數據的時候,反序列化的7個字段中,type直接就是ValueInt,尷尬了。
因此,我發現了個很尷尬的問題,它自己取的列屬性是enum,反序列出來的值類型是int。這裏是它引擎自己的事,和框架無關。
解決辦法
沒有找資料看別人怎麼弄,不過看源代碼這裏找到了出現原因和問題所在,我先考慮從代碼層面嘗試解決,按規範定義java bean,把這個字段定義爲enum類型映射,明知道其實和這個關係不大(即使直接執行原生sql也是這問題),還想試下。
果然,重啓之後,結果還是報這個錯。
然後,想着把db中enum的字段字義改長點,超過10位,如:
alter table T_VIP_USERS alter column type set data type enum('complex_card', 'haircut_card') ;
測試更新money卻報type字段 too long這個問題已經沒有了,,,然後測試了下代碼的插入操作也沒有問題了。只是覺得這個問題解決的很尷尬,不像正道。。。