Small pit encountered when JDBC connects to MySQL

I recently switched from MS SQL Server to MySQL, which is already version 8.11. It seems that a new authentication method was used during the installation. The connection process is also stumbling, and many strange problems are encountered, which are recorded here. .


 

Driver loading:

When using JDBC in the past, we imported the corresponding JDBC driver jar package, and then used

Class.forName(driverName);

Load the driver, and then connect to the database. When using MySQL version 8.11 and its corresponding Connector, if the above code is used to load com.mysql.jdbc.Driver, the console will output a line of information:

Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.

It probably means that the loaded class has been deprecated. The new driver class is com.mysql.cj.jdbc.Driver, which is automatically registered through SPI and usually does not need to be loaded manually. Running after commenting out Class.forName will not produce this output.

URL when connecting to database:

The format of the first half of the URL is fixed, and the parameters that need to be added are attached to the back through QueryString in a similar URL. The format is as follows:

jdbc:<_database>://<address>:<port>/<database_name>[?_key1=_value1[&_key2=_value2[&_key3=_value3]...]]

 


 

Here are just a few parameters used:

When connecting without parameters, the first line of prompt information will be output:

Tue May 08 20:16:40 CST 2018 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.

It probably means that it is not recommended to establish an SSL connection without server authentication, etc. Since I don't know much about SSL, I just follow the prompts and add the parameter useSSL=false , and the output will not be generated.


 

The next error encountered is a SQLException about time zones: The server time zone value...

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.

It probably means that there is a problem with the time zone value of the server. I am just a mess of garbled characters. Add the parameter serverTimezone=Hongkong according to the prompt , and this exception will not occur. For the value of this parameter, you can refer to the relevant information to obtain it. It is known that East 8 can use Hongkong, Asia/Shanghai or Asia/Hongkong as the parameter value .


 

SQLNonTransientConnectionException: Public Key Retrieval is not allowed

At this time, the program may have been able to connect to the database normally, but when I connected again the next day after the debugging was successful (without making any changes to the code), an exception was thrown and the connection failed, and multiple attempts were unsuccessful. The exception is as follows:

SQLNonTransientConnectionException: Public Key Retrieval is not allowed

There is very little online related information about this abnormality, mostly in English. The problem is solved by mistake. The method is to add a parameter allowPublicKeyRetrieval=true , you can connect normally, and after the connection is successful once, you can still delete this parameter. Normal connection (not knowing is metaphysics)..., this method comes from ( https://bugs.mysql.com/bug.php?id=75670 ) the next dalao comment:

[20 Aug 2015 19:57] Daniel So
Added the following entry to the Connector/J 6.0 changelog:

"If the MySQL server's default authentication method was SHA256 but neither one of the Connector/J connection properties allowPublicKeyRetrieval and serverRSAPublicKeyFile was set, the authentication failed with a TransientConnectionException, complaining that the public key could not be retrieved. With this fix, authentication continues in the situation, allowing other enabled authentication methods to be tried."

However did not understand.


 

The other is the character encoding problem . The default encoding used by my server is UTF-8MB4, and the default encoding of Eclipse is UTF-8, so the encoding problem is not dealt with.

If encoding conversion is required, additional parameters useUnicode=true and characterEncoding=UTF-8 are required .


 

Other important parameters (from: https://blog.csdn.net/wpydaguan/article/details/41148047 ):

parameter name Parameter Description Default value Minimum version requirements
user Database username (for connecting to the database)   all versions
password User password (for connecting to the database)   all versions
useUnicode Whether to use the Unicode character set, if the parameter characterEncoding is set to gb2312 or gbk, the value of this parameter must be set to true false 1.1g
characterEncoding Specifies the character encoding when useUnicode is set to true. For example, it can be set to gb2312 or gbk false 1.1g
autoReconnect When the database connection is abnormally interrupted, is it automatically reconnected? false 1.1
autoReconnectForPools Whether to use the reconnection strategy for the database connection pool false 3.1.3
failOverReadOnly After the automatic reconnection is successful, is the connection set to read-only? true 3.0.12
maxReconnects The number of times to retry the connection when autoReconnect is set to true 3 1.1
initialTimeout When autoReconnect is set to true, the time interval between two reconnects, in seconds 2 1.1
connectTimeout The timeout for establishing a socket connection with the database server, in milliseconds. 0 means never timeout, for JDK 1.4 and later 0 3.0.1
socketTimeout Socket operation (read and write) timeout, in milliseconds. 0 means never timeout 0 3.0.1

 


pay attention! In some cases where the URL is specified through a configuration file (such as an xml configuration file), the isolation symbol & of the parameter after the URL needs to be escaped with & as &, as well as other symbols:

Special characters commonly used in HTML (Character Entities)

Show results illustrate Entity Name Entity Number
  显示一个空格 &nbsp; &#160;
< 小于 &lt; &#60;
> 大于 &gt; &#62;
& &符号 &amp; &#38;
双引号 &quot; &#34;

 

其他常用的字符实体(Character Entities)

显示结果 说明 Entity Name Entity Number
? 版权 &copy; &#169;
? 注册商标 &reg; &#174;
× 乘号 &times; &#215;
÷ 除号 &divide; &#247;

Java Web中遇到的坑:

No suitable driver found for jdbc:mysql://...

前面提到MySQL启用的旧驱动使用了新的通过SPI自动注册的驱动,在普通Java程序下可以正常运行,但是在Java Web项目中运行在Tomcat8.5环境下时,进行数据库连接操作会抛出异常:

java.sql.SQLException: No suitable driver found for jdbc:mysql://...

大概的意思是找不到合适的JDBC驱动程序,经过检查,已经将使用到的驱动jar包放到了Tomcat的lib目录下,Eclipse中的构建路径也包含了该jar包,在执行连接操作前向控制台打印所用驱动类也存在:

			System.out.println(com.mysql.cj.jdbc.Driver.class);

/*
*输出:
**
*class com.mysql.cj.jdbc.Driver
*
*/

经过搜索得到的答案基本一致(转自:http://www.blogjava.net/w2gavin/articles/217864.html):

    今天出现编码出现了No suitable driver found for jdbc,又是找遍了网上的资料,基本上都说是三个问题:
    一是:连接URL格式出现了问题(Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/XX","root","XXXX")
    二是:驱动字符串出错(com.mysql.jdbc.Driver)
    三是Classpath中没有加入合适的mysql_jdbc驱动
    经过我的仔细检查,这三种错误我都没有犯,为什么呢?
    尝试着将mysql-connector-java-3.1.14-bin.jar的jar包加入C:\Program Files\Java\jre1.6.0_02\lib\ext文件夹下,问题解决了!!
    原来是不仅仅要求将驱动加入classpath中,而且需要将该jar包加入到java运行环境的外部jar包中,唉,下次这种低级错误还是少犯为妙。 

对于这三个说法,本人针对前两条进行了检查,并没有错误,第三条个人认为不正确,Tomcat会自动加载lib下的jar包,况且上面在打印驱动类的Class对象时也确实能看到该类已经被加载,对于下面将驱动jar包放入系统jre下的方(玄)法(学)也并未尝试不过,在连接数据库操作前加了主动加载驱动类的代码后竟然神(玄)奇(学)的好了

			System.out.println(com.mysql.cj.jdbc.Driver.class);
			Class.forName(driverName);
			System.out.println("connecting...");
			conn = DriverManager.getConnection(URL, uName, uPwd);
			System.out.println("connect success!");
/*
*输出:
**
*class com.mysql.cj.jdbc.Driver
*connecting...
*connect success!
*
*/

可以看到在手动加载之前该类已经注册,因此这个玄学问题还希望请知道的dalao指教一二!


目前遇到的问题就这些,日后遇到新的问题继续补充,文中理解的若有错误还请dalao们指正,欢迎大家的讨论交流。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325917836&siteId=291194637