错误产生的环境
在spring boot整合mybatis数据库中出现以上报错,配置信息写在yml或者yaml的配置文件中;并且数据库密码是全数字,并且以0开头。
例如如下的数据库配置。
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test
username: root
password: 000000
server:
port: 80
问题
在数据库用户名和密码都输入正确的情况下仍然报错
java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129) ~[mysql-connector-j-8.0.32.jar:8.0.32]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-j-8.0.32.jar:8.0.32]
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:824) ~[mysql-connector-j-8.0.32.jar:8.0.32]
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:444) ~[mysql-connector-j-8.0.32.jar:8.0.32]
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:237) ~[mysql-connector-j-8.0.32.jar:8.0.32]
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:198) ~[mysql-connector-j-8.0.32.jar:8.0.32]
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138) ~[HikariCP-4.0.3.jar:na]
...
原因
由于yaml文件的读取方式导致的密码错误,yaml文件读取数字属性时先转化成Integer类型,如果需要的是String类型的数据,再将Integer类型转换成String类型的数据。
值得注意的是,yaml文件读取数值类型会按照数字常量的前缀来读取不同进制的数值类型,例如二进制 (Binary) 前缀为 0b 或 0B。八进制 (Octal) 前缀为 0。十进制 (Decimal) 无前缀。十六进制 (Hex) 前缀为 0x 或 0X。
通过源码进行调试可知,000000的数据库密码会读取转化为"0"的字符串,调试结果如下:
而011会被解析成八进制数值,就是十进制的9,因此密码会被读取为"9"的字符串,调试结果如下:
那么0x11会被解析为十进制的17,调试结果如下:
解决措施
为了防止密码或者用户名解析为数值类型,将解决措施将 username 和 password 中的值加上双引号,解析为字符串类型,防止错误解析。
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test
username: "root"
password: "000000" # 添加引号的原因是防止密码中出现特殊字符,导致解析错误及类型转换错误
server:
port: 80
测试是否解决
成功解决问题,这个问题比较特殊,一般数据库密码不可能纯数字,因此企业开发中基本不会遇到