MySQL JDBC驅動版本與資料庫版本的對應關係及注意事項

Zxeao 發表於 2022-11-24
資料庫 MySQL JDBC

MySQL JDBC驅動版本與資料庫版本的對應關係及注意事項

事情發生

學了三遍的servlet,經典老師又教的第一萬遍登陸註冊,並且讓實現,並且讓演示,我們老師可能和之前的小學期公司老師
完全沒有溝透過,我們小學期大作業都做了一個小專案出來還擱這登陸註冊。
就把五個月前寫的一個小專案拿出來,是一個類似菜鳥教程的網站,不過只有java的教程,這都是後話,

專案地址為:https://gitee.com/zxeao/Study_Station.git
大佬有興趣可以看看

裡面有登入註冊,就想著跑一下,給老師演示演示得了,問題出現了,因為之前的伺服器過期了,我把資料庫環境搭在自己的電腦上,跑起來之後,後臺報錯,前端登入也是500錯誤,這就奇了怪了。

錯誤緣由

前端報錯如下:
image
這誰受得了,自己親生的專案在自己手裡跑不起來,於是研究了一下報錯,

java.sql.SQLException: The server time zone value '???ú±ê×??±??' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89)
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63)
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:73)
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:76)
	at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:835)
	at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:455)
	at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:240)
	at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:199)
	at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
	at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:228)
	at utils.DBHelper.getConnection(DBHelper.java:27)
	at DAO.UserDao.queryLogin(UserDao.java:22)
	at Controller.loginController.doPost(loginController.java:29)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)

發現問題的根源就在DBHelper包,資料庫沒有連結上,我在idea還是在navicat上都能連線上,正當我百思不得其解,突然想到老師講過,mysql對應的jdbc驅動版本的問題。
查閱相關資料之後,得知是由於jdbc驅動包引發的問題,我之前伺服器上的MySQL版本是8+版本,我檢視了現在本機的MySQL版本
image
果然,版本不一致,我之前在maven裡面配置的也是8.0.15的驅動版本,正想著去找5+資料庫的驅動版本,開啟我的pom一看,
image
這不就有麼?之前做的準備足了現在就不用坐牢了。

解決方法

於是把MySQL驅動的版本換成5.1.38,
image
更新之後,正當我滿心歡喜的等待跑起來,正常登入一下的時候,問題又出現了

java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver
	at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1291)
	at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:375)
	at utils.DBHelper.getConnection(DBHelper.java:24)
	at DAO.UserDao.queryLogin(UserDao.java:22)
	at Controller.loginController.doPost(loginController.java:29)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)

不是,現在版本也對應上了,為什麼還會報錯,跑不起來呢?
問題就在

com.mysql.cj.jdbc.Driver

大家肯定還見過

com.mysql.jdbc.Driver

這倆區別在哪,大家看我最下面的注意事項

就是這倆的問題,當我把cj去掉之後,就跑起來了
image
只能說確實好看。

版本對應

所以我簡單做了個整理,把驅動版本和MySQL資料庫版本做個可用性對應。

mysql-connector-java MySQL JDK 補充
8.0.x 5.6、5.7、8.0 4.2 JDK 8.0或更高版本 全面上市。推薦版本。
5.1.x 5.6、5.7、8.0 3.0、4.0、4.1、4.2 JDK 5.0和JDK 8.0或更高版本 一般可用性

注意事項

jar包名稱

MySQL資料庫8.x版本的驅動檔案jar包對應的是:

Class.forName("com.mysql.cj.jdbc.Driver");

語句來載入資料庫驅動

而我使用的是5.0x版本的資料庫驅動檔案,對此,需要將載入資料庫驅動的語句更改為:

Class.forName("com.mysql.jdbc.Driver");

此外,url的設定也得進行修改,原本的url如下:

String ur="jdbc:mysql://127.0.0.1:3306/study_station";

應修改為如下:

String url="jdbc:mysql://127.0.0.1:3306/study_station?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8";

關於useSSL的選項

8.0x是不需要建立ssl連線的,你需要顯示關閉,即url中的&useSSL=false;

5.0x可以建立ssl連線,如果沒有加useSSL選項,就會報錯

WARN: Establishing SSL connection without server’s identity verification is not recommended. 
According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection 
must be established by default if explicit option isn’t set. 
For compliance with existing applications not using SSL the verifyServerCertificate property is set to ‘false’. 
You need either to explicitly disable SSL by setting useSSL=false, 
or set useSSL=true and provide truststore for server certificate verification.

翻譯

警告:建議不要在沒有伺服器身份驗證的情況下建立SSL連線。
根據MySQL 5.5.45 +,5.6.26+和5.7.6+要求SSL連線
如果未設定顯式選項,則必須預設建立。
為了符合不使用SSL的現有應用程式,verifyServerCertificate屬性設定為“false”。
您需要透過設定useSSL = false顯式禁用SSL,
或者設定useSSL = true併為伺服器證照驗證提供信任庫。

所以5.0x無論使用不使用ssl都要顯式的把設定加上,不然就會報錯。

關於時區:serverTimezone

serverTimezone=GMT%2B8"是進行時區的設定
使用mysql 8.0.16 版本的驅動的時候解決如下報錯:

java.sql.SQLException: The server time zone value '???ú±ê×??±??' is unrecognized or represents more than one time zone.

這是由於資料庫和系統時區差異所造成的,在jdbc連線的url後面加上serverTimezone=GMT即可解決問題,如果需要使用gmt+8時區,需要寫成GMT%2B8,否則會被解析為空。

再一個解決辦法就是使用低版本的MySQL jdbc驅動,5.1.28不會存在時區的問題。

url基本格式如下:

連線地址+ssl連線關閉+字符集為utf-8+時區設定

順便一提

如果輸入中文存在亂碼,可以如下設定:

jdbc:mysql://127.0.0.1:3306/hello?useUnicode=true&characterEncoding=UTF-8

當然,為了時間什麼的穩妥,你也可以都寫上 如下:

jdbc:mysql://127.0.0.1:3306/hello?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC

搞定。