JDBC亂碼引發的"血案"

胖先森發表於2018-04-08

JDBC的設定說明

在安裝MySQL的時候,我遇到學生沒有按照規矩設定,導致JDBC連線資料庫後,對資料庫的操作出現亂碼問題,那個時候我就匆忙的給學生新增了一下連線設定,但是學生並沒有太懂,所以在這裡我簡單介紹一下.

出現亂碼的問題無外乎就是編碼設定的不統一導致的!

  • 可能是程式碼的編碼與資料庫的編碼不同
    • 注意以後全部使用UTF-8格式就好
jdbc:mysql://localhost:3306/資料庫名?useUnicode=true&characterEncoding=UTF-8
複製程式碼

作用說明: 指定字元的編碼/解碼的格式

情景描述

mysql資料庫用的是GBK編碼,而專案資料庫用的是utf-8編碼.這時候如果新增了useUnicode=true&characterEncoding=UTF-8,那麼作用有如下兩個方面:

  1. 儲存資料時

    資料庫在存放專案資料的時候會先用UTF-8格式將資料解碼成位元組碼,然後再將解碼後的位元組碼重新使用GBK編碼存放到資料庫中。

  2. 獲取資料時

    在從資料庫中取資料的時候,資料庫會先將資料庫中的資料按GBK格式解碼成位元組碼,然後再將解碼後的位元組碼重新按UTF-8格式編碼資料,最後再將資料返回給客戶端。

注意: 在xml配置檔案中配置資料庫utl時,要使用&的轉義字元也就是&

JDBC屬性說明

jdbc:mysql://[host][,failoverhost...][:port]/[database] »[?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]
複製程式碼
引數名稱 預設值 最低版本要求 引數描述
user 所有版本 資料庫使用者名稱(用於連線資料庫)
password 所有版本 使用者密碼(用於連線資料庫)
useUnicode false 1.1g 是否使用Unicode字符集
characterEncoding false 1.1g 指定字元編碼
autoReconnect false 1.1 當資料庫連線異常中斷時,是否自動重新連線?
autoReconnectForPools false 3.1.3 是否使用針對資料庫連線池的重連策略
failOverReadOnly true 3.0.12 自動重連成功後,連線是否設定為只讀?
maxReconnects 3 1.1 autoReconnect設定為true時,重試連線的次數
initialTimeout 2 1.1 autoReconnect設定為true時,
兩次重連之間的時間間隔,單位:秒
connectTimeout 0 3.0.1 和資料庫伺服器建立socket連線時的超時,單位:毫秒。 0表示永不超時,適用於JDK 1.4及更高版本
socketTimeout 0 3.0.1 socket操作(讀寫)超時,單位:毫秒。 0表示永不超時

對應中文環境,通常MySQL連線URL可以設定為:

jdbc:mysql://localhost:3306/database?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=TRUE&failOverReadOnly=false
複製程式碼

autoReconnect=true : 如果你已經升級好了mysql-connector,其中的characterEncoding=utf8可以被自動被識別為utf8mb4(當然也相容原來的utf8),而autoReconnect配置我強烈建議配上,我之前就是忽略了這個屬性,導致因為快取緣故,沒有讀取到DB最新配置,導致一直無法使用utf8mb4字符集,多麼痛的領悟!!

在以後的MyBatis中處理多條SQL語句的時候,因為MySQL驅動沒有開啟批量執行SQL的開關,我們需要再MySQL連線的URL時候,為其加上allowMultiQueries引數,設定為true

jdbc:mysql://127.0.0.1:3306/database?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
複製程式碼

在使用資料庫連線池的時候,最好設定如下兩個引數

autoReconnect=true&failOverReadOnly=false

MySQL SQL語句別名不生效問題:useOldAliasMetadataBehavior

為增強可讀性指定別名,有相同名字的時候用別名區分,需要被聯查多次的時候用別名區分.

jdbc:mysql://localhost/openemm?useUnicode=yes&characterEncoding=UTF-8&useOldAliasMetadataBehavior=true
其中:
+ jdbc: mysql://localhost/openemm?這個代表資料庫連結地址,
+ useUnicode=yes&characterEncoding=UTF-8這個代表允許使用者自己設定資料庫編碼,而且設定成UTF-8
+ useOldAliasMetadataBehavior=true這個代表資料庫裡面允許有別名
複製程式碼

連線後再資料庫中查詢不到資料

明明資料庫內有符合條件的資料,但是就是無法查詢到?可能是犯了以一個低階的錯誤。

資料庫內儘量不要使用nchar()這種格式,因為固定了位數,當資料的位數不夠的時候就會使用空字元來佔位。如:

name nchar(10) -->施維新

使用String輸出時,會看到施維新□□□□□□□
複製程式碼

同時nchar()格式會比較浪費空間,如無必要,不建議使用。

附錄

JDBC亂碼引發的"血案"

相關文章