MySQL JDBC 中 tinyint(1) 处理为Boolean 的代码逻辑

MySQL JDBC 中 tinyint(1) 类型,在查询时默认会被处理为 Boolean 类型。

参数配置

官方文档中提供了参数配置

上图标记的两个参数可以控制如何处理 tinyint(1) 类型和 BIT 类型。

tinyInt1isBit 默认 true,因此会把 tinyint(1) 类型转换为 BIT 类型。

转换的逻辑在 com.mysql.jdbc.Field 类中的构造方法,相关的部分代码如下:

1
2
3
4
5
6
7
8
9
10
11
if (this.sqlType == Types.TINYINT && this.length == 1 
&& this.connection.getTinyInt1isBit()) {
// Adjust for pseudo-boolean
if (conn.getTinyInt1isBit()) {
if (conn.getTransformedBitIsBoolean()) {
this.sqlType = Types.BOOLEAN;
} else {
this.sqlType = Types.BIT;
}
}
}

这里可以看到最后的 sqlType 属性会变成 Types.BIT 类型。

取值时为什么会变成 Boolean 类型呢?

类型对应关系

先看官方文档中SQL类型和Java类型的对应关系

这里可以看到 BIT 类型转换为了 Boolean 类型。这个转换规则和取值调用的具体方法有关。

通过 ResultSet.getInt(int columnIndex) 方法调用时,tinyint(1) 可以返回正常的 0~9 的值,通过 ResultSet.getBoolean(int columnIndex) 时,会按照一定的规则转换为 Boolean 类型。

只有当通过调用 ResultSet.getObject(int columnIndex) 方法时,才会按照前面 Field 中的 sqlType 类型去调用对应的 getXX类型(int columnIndex) 方法,在 com.mysql.jdbc.ResultSetImpl 中的 getObject 方法的部分代码如下:

1
2
3
4
5
6
7
8
9
switch (field.getSQLType()) {
case Types.BIT:
if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT && !field.isSingleBit()) {
return getObjectDeserializingIfNeeded(columnIndex);
}
return Boolean.valueOf(getBoolean(columnIndex));

case Types.BOOLEAN:
return Boolean.valueOf(getBoolean(columnIndex));

这里会通过 getBoolean(columnIndex) 取值,结果是 Boolean 类型。

MySQL 参数中的 transformedBitIsBoolean 只是觉得是否直接把 sqlType 从 BIT 转换为 Boolean 类型,不管是否转换,在 Java 中都是 Boolean 类型。

如果不想让 tinyint(1) 类型处理为 Boolean 类型,设置 tinyInt1isBit=false参数即可。

测试代码

下面是可以用来测试的代码,创建数据库,添加下面的测试表:

1
2
3
4
5
6
7
CREATE TABLE `test_bit` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`test` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

INSERT INTO `test_bit`(`test`) VALUES (0), (1), (2);

纯JDBC测试代码(注意添加mysql驱动):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[] args) throws SQLException {
//注意修改数据库test和账号密码
//添加或去掉&tinyInt1isBit=false参数查看差异
Connection connection = DriverManager.getConnection(
"jdbc:mysql://127.0.0.1:3306/test?useSSL=false&tinyInt1isBit=false", "root", "root");
PreparedStatement preparedStatement = connection.prepareStatement("select test from test_bit");
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
Object object = resultSet.getObject(1);
System.out.println("test: " + object + ", class: " + object.getClass());
}
resultSet.close();
preparedStatement.close();
connection.close();
}

MySQL JDBC 中 tinyint(1) 处理为Boolean 的代码逻辑
https://blog.mybatis.io/post/f7793597.html
作者
Liuzh
发布于
2023年2月16日
许可协议