当前位置: 首页 > news >正文

解决 MyBatis/MyBatis-Plus 中 UUID 类型转换错误的最佳实践

问题背景

在使用 MyBatis 或 MyBatis-Plus 进行数据库操作时,开发者经常会遇到类似这样的错误:

Error attempting to get column 'ID_' from result set. 
Cause: java.sql.SQLDataException: 
Cannot determine value type from string 'd6730c90-608b-11f0-af5f-085bd679012a'

这个错误表明框架无法将数据库中的字符串值正确地转换为 Java 对象中的字段类型。本文将深入分析这个问题,并提供多种解决方案。

错误原因深度分析

1. 类型不匹配

数据库存储的可能是:

  • UUID 格式的字符串(VARCHAR/CHAR)
  • 二进制格式的 UUID(BINARY)
  • 数据库原生 UUID 类型(如 PostgreSQL 的 UUID 类型)

而 Java 实体类中可能定义为:

  • String 类型
  • java.util.UUID 类型
  • 其他自定义类型

2. 框架处理机制

MyBatis 的类型处理流程:

  1. 从 ResultSet 获取数据
  2. 根据 Java 类型选择合适的 TypeHandler
  3. 执行类型转换
  4. 设置到 Java 对象属性

当这个流程中任一步骤出现类型不匹配时,就会抛出上述异常。

解决方案大全

方案1:统一数据库和Java类型

场景A:数据库存储为字符串

@Entity
@Table(name = "your_table")
public class YourEntity {@Id@Column(name = "ID_")private String id; // 使用String类型// 其他字段...
}

场景B:数据库使用原生UUID类型

@Entity
@Table(name = "your_table")
public class YourEntity {@Id@Column(name = "ID_")private UUID id; // 使用java.util.UUID// 其他字段...
}

方案2:使用自定义TypeHandler

public class UUIDTypeHandler extends BaseTypeHandler<UUID> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, UUID parameter, JdbcType jdbcType) throws SQLException {ps.setString(i, parameter.toString());}@Overridepublic UUID getNullableResult(ResultSet rs, String columnName) throws SQLException {String value = rs.getString(columnName);return value == null ? null : UUID.fromString(value);}// 其他必要方法...
}

注册TypeHandler:

@MappedTypes(UUID.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class UUIDTypeHandler extends BaseTypeHandler<UUID> {// 实现...
}

方案3:MyBatis-Plus特殊配置

mybatis-plus:type-handlers-package: com.yourpackage.handlersconfiguration:default-enum-type-handler: org.apache.ibatis.type.EnumTypeHandler

方案4:数据库端解决方案

PostgreSQL示例

-- 创建表时指定UUID类型
CREATE TABLE your_table (ID_ UUID PRIMARY KEY,-- 其他字段...
);-- 或者在已有表上修改
ALTER TABLE your_table ALTER COLUMN ID_ TYPE UUID USING ID_::UUID;

MySQL示例

-- 使用BINARY(16)存储UUID
CREATE TABLE your_table (ID_ BINARY(16) PRIMARY KEY,-- 其他字段...
);

最佳实践建议

  1. 保持一致性原则

    • 在整个应用中统一使用String或UUID类型
    • 避免混用不同类型
  2. 性能考虑

    • 字符串存储占用36字节
    • 二进制存储仅需16字节
    • 原生UUID类型性能最佳
  3. 可读性权衡

    • 字符串形式更易读和调试
    • 二进制形式需要转换才能阅读
  4. 迁移兼容性

    • 考虑未来可能的数据库迁移
    • 选择最通用的解决方案

常见问题排查清单

  1. 检查数据库实际存储类型

    SELECT column_name, data_type 
    FROM information_schema.columns 
    WHERE table_name = 'your_table';
    
  2. 验证实体类映射是否准确

    • 检查@Column注解
    • 验证@TypeHandler配置
  3. 检查JDBC连接参数

    • PostgreSQL可能需要stringtype=unspecified
    • MySQL可能需要useSSL=false等参数
  4. 查看完整异常堆栈

    • 定位问题发生的具体位置
    • 检查是否有拦截器修改了数据

总结

UUID类型处理错误是MyBatis/MyBatis-Plus开发中的常见问题,但通过理解其背后的机制和采用适当的解决方案,可以轻松应对。关键在于保持数据库设计和Java类型系统的一致性,并在必要时使用TypeHandler进行灵活转换。

选择哪种解决方案取决于你的具体需求:

  • 简单应用:统一使用String类型
  • 高性能需求:使用二进制存储+TypeHandler
  • 使用PostgreSQL等支持原生UUID的数据库:直接使用UUID类型

希望本文能帮助你彻底解决这个问题,如果有任何特殊情况或进一步的问题,欢迎留言讨论!

http://www.dtcms.com/a/284445.html

相关文章:

  • OC—初识UIStackView
  • 线程安全集合——CopyOnWriteArrayList
  • FRP配置( CentOS 7 上安装 FRP教程 )
  • MySql查询 值存在但查不到
  • 深度学习G3周:CGAN入门(生成手势图像)
  • 理解欧拉角:定义、转换与应用
  • HTTPS的工作原理及DNS的工作过程
  • 【LeetCode 热题 100】108. 将有序数组转换为二叉搜索树
  • SpringBoot使用ThreadLocal共享数据
  • 2021-07-21 VB窗体求范围质数(Excel复制工作簿)
  • Python 基础语法与数据类型(十三) - 实例方法、类方法、静态方法
  • 【测试100问】没有接口文档的情况下,如何做接口测试?
  • MinIO:开源对象存储解决方案的领先者
  • DiffPy-CMI详细安装教程
  • 【Vue进阶学习笔记】组合式API(Composition API)
  • Go 程序无法使用 /etc/resolv.conf 的 DNS 配置排查记录
  • React hooks——memo
  • 【软件开发】主流 AI 编码插件
  • 关于el-table异步获取数据渲染动态列数据赋值列数据渲染时title高度异常闪过问题
  • 深度解析:基于EasyX的C++黑白棋AI实现 | 算法核心+图形化实战
  • 数据呈现进阶:漏斗图与雷达图的实战指南
  • 基于Echarts的气象数据可视化网站系统的设计与实现(Python版)
  • Idea使用git不提示账号密码登录,而是输入token问题解决
  • 【解决方案】yakit流量转发到mitmproxy
  • 浅谈 awk 中管道的用法
  • zynq mpsoc switch级联ssd高速存储方案
  • 贴吧项目总结二
  • mysql——搭建MGR集群
  • CommonJS 功能介绍
  • 基于dcmtk的dicom工具 第二章 图像接受StoreSCP(2)