隐式转换问题

【 使用环境 】生产环境
【 OB or 其他组件 】ob4.2.1
【 使用版本 】
【复现路径】
update family_member set memberPhone = #{memberPhone} where id = #{id}
上述sql在mybatis执行会报错,id在vo里面是long类型,id在family_member是varchar的。

错误如下
org.springframework.dao.TransientDataAccessResourceException:

Error updating database. Cause: java.sql.SQLException

The error may exist in URL [jar:file/SurvivalCertificationMapper.xml]

The error may involve defaultParameterMap

The error occurred while setting parameters

SQL: update family_member set memberPhone = ? where id = ?

Cause: java.sql.SQLException; null; nested exception is java.sql.SQLException

同样的情况下,我们测试环境的mysql没报错。
是因为ob的驱动更严格吗,还是不支持这种long转换string?

@论坛小助手 OB隐式转换支持long转换string么

根据文档库中的信息以及对OceanBase数据库的理解,可以对您的问题进行如下解答:

1. 关于隐式类型转换

  • OceanBase 社区版在 SQL 执行时,对于隐式类型转换的规则与 MySQL 并不完全一致。虽然 OceanBase 力求兼容 MySQL 的行为,但在某些场景下可能会更加严格。
  • 在您提供的 SQL 中,id 列的类型为 varchar,而传入的参数是 long 类型。这种情况下,OceanBase 数据库需要将 long 类型的参数隐式转换为 varchar 类型以匹配列的定义。

2. 错误原因分析

  • 根据错误信息 org.springframework.dao.TransientDataAccessResourceExceptionjava.sql.SQLException,可以推测问题出在参数绑定阶段。
  • OceanBase 数据库可能不允许直接将 long 类型的参数隐式转换为 varchar 类型,尤其是在驱动层面或 SQL 解析阶段。
  • 测试环境中的 MySQL 没有报错,可能是因为 MySQL 对隐式类型转换的处理更加宽松。

3. 解决方案

针对您的问题,建议采取以下措施之一:

方法一:显式转换

在 MyBatis 的 Mapper 文件中,将 #{id} 的值显式转换为字符串类型。例如:

<update id="updateFamilyMember">
    UPDATE family_member 
    SET memberPhone = #{memberPhone} 
    WHERE id = CAST(#{id} AS CHAR)
</update>

这样可以确保传递给 OceanBase 的参数类型与 id 列的类型一致。

方法二:调整 VO 定义

如果可能,将 id 字段在 VO 中的类型从 long 修改为 String,以避免类型不匹配的问题。

方法三:检查驱动版本

确保使用的 OceanBase JDBC 驱动版本与数据库版本兼容。如果驱动版本较旧,可能存在一些类型转换上的限制。您可以尝试升级到最新版本的 OceanBase JDBC 驱动。

4. 是否因为 OB 驱动更严格?

是的,OceanBase 的驱动和 SQL 引擎在某些场景下的行为确实比 MySQL 更加严格。这是为了保证数据的一致性和安全性。例如,在隐式类型转换方面,OceanBase 可能会拒绝执行可能导致数据丢失或精度损失的操作。

5. 总结

  • OceanBase 社区版支持隐式类型转换,但其规则可能比 MySQL 更严格。
  • 建议通过显式转换或调整 VO 定义来解决类型不匹配的问题。
  • 如果仍有疑问,可以联系 OceanBase 的人工答疑团队获取进一步帮助。

希望以上解答能够解决您的问题!如果有其他相关疑问,请随时提问。

检索到的文档如下:

  1. OceanBase 数据库 V4.1.0
  2. 0001 ~ 3999
  3. SpringBoot 连接 OceanBase 数据库
  4. 4000 ~ 4499

可以试一下非严格模式看看。建议还是按正常规范进行开发,毕竟隐式转换存在性能问题。

好的,我们试下

@论坛小助手
OceanBase 数据库可能不允许直接将 long 类型的参数隐式转换为 varchar 类型,尤其是在驱动层面或 SQL 解析阶段

我想知道到底是不是允许,而不是可能不允许

根据文档库中的信息,可以明确以下几点来回答您的问题:

  1. 隐式类型转换规则
    根据文档片段 2 的描述(标题:数据类型转换规则 → 转换方式),OceanBase 数据库支持隐式数据类型转换。隐式转换发生在需要特定数据类型的场景中,而实际参数的类型不匹配时,数据库会尝试将参数转换为目标类型后再执行操作。例如,字符串可以自动转换为数字,反之亦然。

    obclient> SELECT 1+'1';
    +-------+
    | 1+'1' |
    +-------+
    |     2 |
    +-------+
    1 row in set
    

    然而,这种隐式转换的行为依赖于具体的场景和数据类型组合。对于某些类型组合,OceanBase 数据库可能无法完成隐式转换,并会抛出错误。

  2. 关于 LONGVARCHAR 的隐式转换
    根据文档片段 3 和片段 9 的描述(标题分别为:ERROR 5084 和 ERROR 5085),当尝试将不兼容的数据类型进行隐式转换时,OceanBase 数据库会报错。例如:

    • 错误码 5084 表示无法将 VARCHAR 类型的值转换为布尔类型。
    • 错误码 5085 表示无法将 VARCHAR 类型的值转换为数字类型。

    这表明,虽然 OceanBase 支持部分隐式转换,但对于某些类型组合(如 LONGVARCHAR),可能并不支持隐式转换,尤其是在驱动层面或 SQL 解析阶段。

  3. 明确的回答
    根据上述分析,OceanBase 数据库并不保证支持从 LONG 类型到 VARCHAR 类型的隐式转换。这种行为可能是由于以下原因:

    • 驱动层面对参数类型的严格检查。
    • SQL 解析阶段对类型匹配的要求。

    因此,在您的场景中,id 列为 VARCHAR 类型,而传入的参数为 LONG 类型,OceanBase 数据库可能无法完成隐式转换,从而导致错误。

  4. 解决方案建议
    为了确保兼容性和避免类似问题,建议采取以下措施之一:

    • 显式转换:在 SQL 中使用 CAST 函数将 LONG 类型的参数显式转换为 VARCHAR 类型。例如:
      UPDATE family_member 
      SET memberPhone = #{memberPhone} 
      WHERE id = CAST(#{id} AS CHAR);
      
    • 调整参数类型:将 id 字段在 VO 中的类型从 LONG 修改为 String,以确保参数类型与列定义一致。
    • 升级驱动版本:确保使用的 OceanBase JDBC 驱动版本与数据库版本兼容,以获得更好的类型转换支持。
  5. 总结
    综上所述,OceanBase 数据库并不支持从 LONG 类型到 VARCHAR 类型的隐式转换,尤其是在驱动层面或 SQL 解析阶段。为了避免此类问题,建议通过显式转换或调整参数类型来解决。

希望以上解答能够明确您的疑问!如果仍有其他相关问题,请随时提问。

更多信息请查看:

  1. 列操作
  2. 数据类型转换规则
  3. 5000 ~ 5999
  4. 字符类型概述
  5. CAST
  6. CHAR 和 VARCHAR
  7. 列类型变更规则
  8. ob_compatibility_version

long是2 *64方。的那个类型么
long int 还是long txt

vo里面
private Long id;
表定义
private String id;

int 转varchar是支持的。你的long类型是什么呢。

java的long类型,64位的

支持 long int转varchar

好的。
那支持大写的Long转varchar吗?

这个可以自己测一下就知道了