使用mybatis-plus传递的参数类型不同,查询结果不同?

新手上路,请多包涵

使用mybatis-plus传递的参数类型不同,查询结果不同。
mysql版本为8.x。

创建基本数据
create table sys_contract_config(
        id int primary key auto_increment,
        time_range varchar(42) 
)
insert into sys_contract_config VALUES(1, '{"start":"2024-11-01", "end":"2024-12-01"}');
insert into sys_contract_config VALUES(2, '{"start":"2024-12-02", "end":"2024-12-30"}');

我需要根据 time_range字段进行查询出所有开始时间大于等于传入时间的数据。

select * from sys_contract_config where JSON_EXTRACT(time_range, '$.start') >= '2024-11-01'

拿到数据库运行,执行通过之后,将其放入到项目中。

mapper 文件

// 接口定义
List<Map<String, Object>> listContractConfigByLocalDate(@Param("start") LocalDate startDate);

// xml 
<select id="listContractConfigByLocalDate" resultType="java.util.Map">
        select * from sys_contract_config where JSON_EXTRACT(time_range, '$.start') >= #{start}
    </select>

此时传递的参数为 LocalDate 类型,运行测试类后发现没有任何数据返回。
image.png

如果修改入参为Strin,则能正常查询到结果。

或者修改查询语句为

select * from sys_contract_config where JSON_UNQUOTE(JSON_EXTRACT(time_range, '$.start')) >= #{start}

使用 JSON_UNQUOTE() 去除掉取出的 start 字段值的双引号。此时,即使入参的类型为 LocalDate 也能正确查询到数据了。

mybatis-plus 在设置参数时,到底是将 LocalDate 转换成了啥?

阅读 898
avatarAI BotBETA

回答

在 MyBatis-Plus 中,当你使用 LocalDate 类型作为查询参数时,MyBatis-Plus 会将其转换为对应的 SQL 字符串表示形式,通常是使用 JDBC 的 PreparedStatement 机制。然而,这种转换可能不会直接生成一个符合 JSON 字符串比较格式的日期字符串。

在你的例子中,JSON_EXTRACT(time_range, '$.start') 返回的是一个 JSON 字符串(即带有双引号的日期字符串,如 "2024-11-01"),而直接传递 LocalDate 类型参数时,MyBatis-Plus 可能将其转换为不带双引号的日期字符串(如 2024-11-01)。因此,比较操作会因为类型不匹配(字符串与不带引号的字符串字面量)而失败。

这就是为什么当你使用 String 类型作为参数时能够正常查询到结果,因为字符串比较是直接的,不涉及类型转换的问题。

使用 JSON_UNQUOTE() 函数可以去除 JSON 提取结果中的双引号,使得比较操作两边的数据类型一致(都是不带双引号的字符串),从而能够正确查询到数据。

因此,在 MyBatis-Plus 中设置参数时,LocalDate 类型被转换为了一个不带双引号的日期字符串,这与从 JSON 中提取的带双引号的字符串不匹配,导致了查询结果的差异。使用 JSON_UNQUOTE() 可以解决这个问题。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏