• 揭秘Mysql到Java字段类型转换


    有一个问题:

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

    揭秘:

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

    1. // com.mysql.cj.protocol.a.ColumnDefinitionReader#read
    2. /* read the metadata from the server */
    3. Field[] fields = null;
    4. boolean checkEOF = !this.protocol.getServerSession().isEOFDeprecated();
    5. // Read in the column information
    6. fields = new Field[(int) columnCount];
    7. for (int i = 0; i < columnCount; i++) {
    8. NativePacketPayload fieldPacket = this.protocol.readMessage(null);
    9. // next check is needed for SSPS
    10. if (checkEOF && fieldPacket.isEOFPacket()) {
    11. break;
    12. }
    13. fields[i] = unpackField(fieldPacket,
    14. this.protocol.getServerSession().getCharacterSetMetadata());
    15. }

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

    第二步: 读取

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

    1. // com.mysql.cj.jdbc.result.ResultSetImpl#getObject(int)
    2. Field field = this.columnDefinition.getFields()[columnIndexMinusOne];
    3. switch (field.getMysqlType()) {
    4. case BIT:
    5. // 代码省略
    6. return field.isSingleBit() ? Boolean.valueOf(getBoolean(columnIndex)) : getBytes(columnIndex);
    7. case BOOLEAN:
    8. return Boolean.valueOf(getBoolean(columnIndex));
    9. case TINYINT:
    10. return Integer.valueOf(getByte(columnIndex));
    11. case TINYINT_UNSIGNED:
    12. case SMALLINT:
    13. case SMALLINT_UNSIGNED:
    14. case MEDIUMINT:
    15. case MEDIUMINT_UNSIGNED:
    16. case INT:
    17. return Integer.valueOf(getInt(columnIndex));
    18. case INT_UNSIGNED:
    19. case BIGINT:
    20. return Long.valueOf(getLong(columnIndex));
    21. case BIGINT_UNSIGNED:
    22. return getBigInteger(columnIndex);
    23. case DECIMAL:
    24. case DECIMAL_UNSIGNED:
    25. String stringVal = getString(columnIndex);
    26. if (stringVal != null) {
    27. // 代码省略
    28. return new BigDecimal(stringVal);
    29. }
    30. return null;
    31. case FLOAT:
    32. case FLOAT_UNSIGNED:
    33. return new Float(getFloat(columnIndex));
    34. case DOUBLE:
    35. case DOUBLE_UNSIGNED:
    36. return new Double(getDouble(columnIndex));
    37. case CHAR:
    38. case ENUM:
    39. case SET:
    40. case VARCHAR:
    41. case TINYTEXT:
    42. return getString(columnIndex);
    43. case TEXT:
    44. case MEDIUMTEXT:
    45. case LONGTEXT:
    46. case JSON:
    47. return getStringForClob(columnIndex);
    48. case GEOMETRY:
    49. return getBytes(columnIndex);
    50. case BINARY:
    51. case VARBINARY:
    52. case TINYBLOB:
    53. case MEDIUMBLOB:
    54. case LONGBLOB:
    55. case BLOB:
    56. if (field.isBinary() || field.isBlob()) {
    57. // 代码省略
    58. return data;
    59. }
    60. return getBytes(columnIndex);
    61. case YEAR:
    62. return this.yearIsDateType ? getDate(columnIndex) : Short.valueOf(getShort(columnIndex));
    63. case DATE:
    64. return getDate(columnIndex);
    65. case TIME:
    66. return getTime(columnIndex);
    67. case TIMESTAMP:
    68. return getTimestamp(columnIndex);
    69. case DATETIME:
    70. return getLocalDateTime(columnIndex);
    71. default:
    72. return getString(columnIndex);
    73. }

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

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

    原理总结:

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

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

    使用:

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

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

     

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

  • 相关阅读:
    LangChain实战技巧之五:让模型“自动生成”Prompt(提示词)的两种方式
    【特征选择】基于二元多邻域人工蜂群 (BMNABC) 特征选择问题(Matlab代码实现)
    使用Python查询域名IP地址归属方法
    华为认证协作高级工程师 HCIP-Collaboration V3.0(中文版) 预发布通知
    B. Stairs
    力扣(LeetCode)181. 超过经理收入的员工(2022.06.29)
    基于FreeBSD 8.0 Ports配置nginx+php+mysql高性能web平台【解决方案】
    Centos7 部署 Containerd
    3d tiles规范boundingVolume属性学习
    zookeeper(目前只有安装)
  • 原文地址:https://blog.csdn.net/htydowd/article/details/127425575