alibaba / alibaba/p3c

java反射调用及泛型擦除引起的mySql索引失效

Open
#951 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Kotlin
Stars
30.9k
Forks
8k
PR merge metrics
No merged PRs in 30d

Description

## Rule content
【强制】在mybatis sql中,查询条件从泛型集合,例如List、HashMap里取参数时,#{}里必须传javaType,避免数据库隐式转换带来的索引失效等不可预期影响。
正例:
```

select u_id, created_ts
from t_unify_user where u_id in


#{item, javaType=String}

```

反例:
```

select u_id, biz_type
from t_unify_user where u_id in


#{item}

```
## Problem description
上述sql对应的mapper接口为:```List queryUserByUidList(@Param("uids")List uids)```
该接口正常调用没有问题,但由于Java中的泛型是 ‘伪泛型’,程序编译期间会将泛型信息擦除而转变为非泛型类,例如``` List ```和``` List ```在编译后擦除了泛型类型只留下了原始类java.util.List,对于上述的mapper接口,编译后它的入参并不区分```List```和```List```,只是在编写代码时,编译器会做语法检查并拦截。

在现实服务场景中,我们会使用dubbo、hsf的泛化调用功能,服务端会根据传入的接口全限定名,参数列表等信息获取服务句柄,然后进行反射调用,这里的反射调用就会绕过上面所说的编译器拦截,例如可以传入```List```调用上面的mapper接口,由于数据表uid字段设置的是varchar型,传入long值查询时,数据库会发生隐式转换,进而引起索引失效,当表数据量庞大时,会timeout,带来生产问题。

实际线上问题及排查见:https://blog.csdn.net/weixin_45047729/article/details/128103900

大多数人认为在sql中指定jdbcType后,mybatis会按照jdbcType进行类型转换,再操作数据库,其实不然,官网给出的定义是:
![20632f25816a4d26bee3a61be6d05e1b](https://user-images.githubusercontent.com/5178276/209596361-33aebfd6-d452-43ec-97ae-bb5c29d73b0c.jpeg)
jdbcType适用于insert、update、delete操作可空字段的场景;而javaType适用于与HashMap等泛型集合类映射的场景,显式指定javaType可保障符合预期的行为。
原文见:[mybatis – MyBatis 3 | Mapper XML Files](https://mybatis.org/mybatis-3/sqlmap-xml.html)

## Advice
建议在mybatis sql中,查询条件从泛型集合,例如List、HashMap里取参数时,#{}里必须传javaType,避免数据库隐式转换带来的索引失效等不可预期影响。

Contributor guide

No contributing guide indexed for this repository

Research direction

Begin with the rule examples in the issue and the linked MyBatis Mapper XML Files documentation. No repository file or test entry point is named; done should mean detecting query parameters taken from generic collections without an explicit javaType and covering the stated List and HashMap cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
tooling
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.