揭秘Mysql到Java字段类型转换

12 篇文章 0 订阅

有一个问题:

数据库表中定义一个字段A,类型int;使用Java 通过Mysql驱动读取的时候,获取的 Java类型就是 Integer;把字段A的类型修改成bit类型,再读取时,获取的Java类型就是Boolean类型,这是怎么做到的呢?

揭秘:

第一步:驱动 读取 数据库 表字段类型

   // com.mysql.cj.protocol.a.ColumnDefinitionReader#read 
       /* read the metadata from the server */
        Field[] fields = null;
        boolean checkEOF = !this.protocol.getServerSession().isEOFDeprecated();

        // Read in the column information

        fields = new Field[(int) columnCount];

        for (int i = 0; i < columnCount; i++) {
            NativePacketPayload fieldPacket = this.protocol.readMessage(null);
            // next check is needed for SSPS
            if (checkEOF && fieldPacket.isEOFPacket()) {
                break;
            }
            fields[i] = unpackField(fieldPacket, 
            this.protocol.getServerSession().getCharacterSetMetadata());
        }

通过第一步,我们再 表中定义的 字段 类型 就拿到了。 既然拿到了字段类型,那么 就可以 转换成对应的Java类型了。

第二步: 读取

读取某个字段的值时,首先会获取 对应字段的 Field 对象,该对象中定义了 当前字段的类型,根据不同的类型,使用不用的方式来读取数据。

        // com.mysql.cj.jdbc.result.ResultSetImpl#getObject(int)
        Field field = this.columnDefinition.getFields()[columnIndexMinusOne];
        switch (field.getMysqlType()) {
            case BIT:
                // 代码省略
                return field.isSingleBit() ? Boolean.valueOf(getBoolean(columnIndex)) : getBytes(columnIndex);

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

            case TINYINT:
                return Integer.valueOf(getByte(columnIndex));

            case TINYINT_UNSIGNED:
            case SMALLINT:
            case SMALLINT_UNSIGNED:
            case MEDIUMINT:
            case MEDIUMINT_UNSIGNED:
            case INT:
                return Integer.valueOf(getInt(columnIndex));

            case INT_UNSIGNED:
            case BIGINT:
                return Long.valueOf(getLong(columnIndex));

            case BIGINT_UNSIGNED:
                return getBigInteger(columnIndex);

            case DECIMAL:
            case DECIMAL_UNSIGNED:
                String stringVal = getString(columnIndex);

                if (stringVal != null) {
                    // 代码省略
                   return new BigDecimal(stringVal);
                }
                return null;

            case FLOAT:
            case FLOAT_UNSIGNED:
                return new Float(getFloat(columnIndex));

            case DOUBLE:
            case DOUBLE_UNSIGNED:
                return new Double(getDouble(columnIndex));

            case CHAR:
            case ENUM:
            case SET:
            case VARCHAR:
            case TINYTEXT:
                return getString(columnIndex);

            case TEXT:
            case MEDIUMTEXT:
            case LONGTEXT:
            case JSON:
                return getStringForClob(columnIndex);

            case GEOMETRY:
                return getBytes(columnIndex);

            case BINARY:
            case VARBINARY:
            case TINYBLOB:
            case MEDIUMBLOB:
            case LONGBLOB:
            case BLOB:
                if (field.isBinary() || field.isBlob()) {
                       // 代码省略
                    return data;
                }

                return getBytes(columnIndex);

            case YEAR:
                return this.yearIsDateType ? getDate(columnIndex) : Short.valueOf(getShort(columnIndex));

            case DATE:
                return getDate(columnIndex);

            case TIME:
                return getTime(columnIndex);

            case TIMESTAMP:
                return getTimestamp(columnIndex);

            case DATETIME:
                return getLocalDateTime(columnIndex);

            default:
                return getString(columnIndex);
        }

如果读取的字段想转成自己指定的类型,那么可以在获取字段数据时指定具体的期望转换的类型就可以了。本来是Boolean类型:

指定为Integer类型读取的对象就是Integer类型

原理总结:

数据库驱动 从 数据库服务 获取到 数据流之后,也就是字节数组,会根据 字段的实际类型,从字节数组中 读取 指定的 字节数,将字节转换成对应的Java对象类型。

有了字节数组,有了起始位置,有了长度,有类型转换工厂。那么 反序列化 之后,就得的我们需要的数据了。

使用:

如果 数据库字段类型 和 Java 定义的 字段类型不一致,只要 类型转换 没问题,程序就没问题。比如: 数据库字段类型是 bit, 读取到Java类型是BigDecimal,一样没问题

字段类型是bit,读取到Java类型是 Date,会报错:

 

了解这些之后,对使用 数据库字段类型 和 Java 字段类型 就能更好的把握。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值