MySql的JDBC连接url地址的各项配置说明及所解决的问题

首先看一条jdbc的url地址:

 `url: jdbc:mysql://127.0.0.1:3306/test?useAffectedRows=true&autoReconnect=true&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai`

接下来将逐步解析里面的配置及所解决的问题

1.useAffectedRows=true

当我们进行update操作时,时常会根据update的结果进行一些逻辑判断,如返回值大于1表示更新成功,为0表示更新失败。
但是使用Mysql驱动连接数据库并进行update操作时,返回值可能不在预期。

如SQL1:update task_info SET task_status=2 where id=?
这个sql无论执行多少遍,update返回值都可能是1。原因在于MySQL的连接URL。
对mysqlURL进行修改,添加参数useAffectedRows=true

jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8&useAffectedRows=true

useAffectedRows的作用在于是否用受影响的行数替代查找到的行数来返回数据,默认 false。指定这个值后,更新时会返回更新的行数,按照SQL1执行update操作也会返回正常值,即第一次返回1,第二次返回0.

2.autoReconnect=true

连接数据库超时设置autoReconnect=true,默认重试次数调整

驱动程序是否应该尝试重新建立连接? 如果启用了,驱动程序将会对陈旧或死亡连接上发出的查询抛出异常,这些查询属于当前事务,但是在新事务中对连接发出的下一个查询之前会尝试重新连接。 不推荐这个功能的使用,因为它有副作用与会话状态和数据一致性当应用程序不妥善处理异常,仅设计用于当你无法配置您的应用程序来处理异常造成死亡和陈旧的正确连接。 另外,作为最后一个选项,研究将MySQL服务器变量“wait_timeout”设置为一个较高的值,而不是默认的8小时。

3.useUnicode=true&characterEncoding=utf-8

mysql数据库用的是gbk编码,而项目的mysql数据库需要的是utf-8编码,所以在url后面添加useUnicode=true&characterEncoding=utf-8″,表示在往数据库中存数据时会用UTF-8的格式将数据解码为字节码,然后再将解码后的字节码重新使用GBK编码存放到数据库中。从数据库中取数据时,会将数据按GBK格式解码为字节码,然后再将字节码重新按照UTF-8格式编码数据返回给客户端

4.allowMultiQueries=true

MySQL连接数据库时,添加语句:“allowMultiQueries=true”的作用:
1.可以在sql语句后携带分号,实现多语句执行。
2.可以执行批处理,同时发出多个SQL语句。

5.zeroDateTimeBehavior=convertToNull

在查询 Mysql 数据库的时候,有时候会产生一个异常:

Value ‘0000-00-00 00:00:00’ can not be represented as java.sql.Timestamp. Stacktrace follows:

java.sql.SQLException: Value ‘0000-00-00 00:00:00’ can not be represented as java.sql.Timestamp


Datetimes with all-zero components (0000-00-00 ...): These values cannot be represented reliably in Java. Connector/J 3.0.x always converted them to NULL when being read from a ResultSet. 

关键在于在 Mysql 里 0000-00-00 00:00:00 可能是有效的;而在 Java 中,这样的转换是无效的。

因此,Mysql JDBC 驱动将抛出一个 java.sql.SQLException ,因为 Java 不能识别 0000-00-00 00:00:00 这样的日期格式。

6.useSSL=false

SSL一种加密协议

发现在MySQL5.7之前的版本,安全性较低,存在任何用户都可以连接上的 test 库,所以官方在5.7版本加大了对隐私的保护。并且采用了默认 useSSL = true值防止对数据库的随意修改,到了8.0版本,仍然保留了SSL,并且默认值为 true,所以只要将 “?useSSL= false” 放在url表名后即可。

7.allowPublicKeyRetrieval=true

如果用户使用 sha256_password 认证,密码在传输过程中必须使用 TLS 协议保护,但是如果 RSA
公钥不可用,可以使用服务器提供的公钥;可以在连接中通过 ServerRSAPublicKeyFile 指定服务器的 RSA
公钥,或者AllowPublicKeyRetrieval=True参数以允许客户端从服务器获取公钥;但是需要注意的是
AllowPublicKeyRetrieval=True可能会导致恶意的代理通过中间人攻击(MITM)获取到明文密码,所以默认是关闭的,必须显式开启

8.serverTimezone=Asia/Shanghai

时区设置不妥可能会产生各种问题,下面我们列举下几个常见的问题及解决方法:

8.1 MySQL 内部时间不是北京时间

遇到这类问题,首先检查下系统时间及时区是否正确,然后看下 MySQL 的 time_zone,建议将 time_zone 改为’+8:00’。

8.2 Java 程序存取的时间与数据库中的时间相差 8 小时

出现此问题的原因大概率是程序时区与数据库时区不一致导致的。我们可以检查下两边的时区,如果想统一采用北京时间,则可以在 jdbc 连接串中增加 serverTimezone=Asia/Shanghai,并且 MySQL 方面也可以将 time_zone 改为’+8:00’。

8.3 程序时间与数据库时间相差 13 小时或 14 小时

如果说相差 8 小时不够让人惊讶,那相差 13 小时可能会让很多人摸不着头脑。出现这个问题的原因是 JDBC 与 MySQL 对 “CST” 时区协商不一致。因为 CST 时区是一个很混乱的时区,有四种含义:

美国中部时间 Central Standard Time (USA) UTC-05:00 或 UTC-06:00
澳大利亚中部时间 Central Standard Time (Australia) UTC+09:30
中国标准时 China Standard Time UTC+08:00
古巴标准时 Cuba Standard Time UTC-04:00
MySQL 中,如果 time_zone 为默认的 SYSTEM 值,则时区会继承为系统时区 CST,MySQL 内部将其认为是 UTC+08:00。而 jdbc 会将 CST 认为是美国中部时间,这就导致会相差 13 小时,如果处在冬令时还会相差 14 个小时。

解决此问题的方法也很简单,我们可以明确指定 MySQL 数据库的时区,不使用引发误解的 CST,可以将 time_zone 改为’+8:00’,同时 jdbc 连接串中也可以增加 serverTimezone=Asia/Shanghai。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
社会演员多的头像社会演员多普通用户
上一篇 2023年12月28日
下一篇 2023年12月28日

相关推荐