• 揭秘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 字段类型 就能更好的把握。

  • 相关阅读:
    Google guava之SortedMultiset简介说明
    MYSQL介绍——数据库约束与范式
    实验6 用例图
    核心实验13合集_vlan mapping 和QinQ_ENSP
    亚稳态介绍、危害及如何避免亚稳态
    31-k8s集群svc的代理模式-iptables修改为ipvs
    Java中常见的HttpClient调用方式
    Anaconda3使用Spark的正确方法
    申报设立2022年湖北省博士后创新实践基地条件、时间、流程
    HTML非遗文化网页设计题材【京剧文化】HTML+CSS(大美中国 14页 带bootstarp)
  • 原文地址:https://blog.csdn.net/htydowd/article/details/127425575