Spring Data查询带转换器的List<String>字段参数类型不匹配如何解决
问题原因
- 你的
deliveryCategories字段通过@Convert注解将Java侧的List<String>转换为逗号拼接的字符串存储到数据库,因此该字段在数据库中实际是单个字符串类型,并非集合/数组类型。 - Spring Data JPA的派生查询中,
In关键字会匹配实体字段本身的Java类型:你实体字段的类型是List<String>,所以DeliveryCategoriesIn会要求传入的参数类型为List<List<String>>,而你传入的是List<String>,其中的元素BIKE是字符串类型,和预期的List类型不匹配,因此抛出类型校验错误。 - 即便你调整参数为
List<List<String>>也无法得到正确查询结果:数据库存储的是逗号拼接的单个字符串,原生SQL的IN语法是匹配多个独立值,无法直接匹配单个字符串内的逗号分隔子项。
解决方案
方案1:改用数据库原生集合类型存储(推荐)
如果使用的数据库支持数组/JSON集合类型(比如PostgreSQL的varchar[]、MySQL 5.7+的JSON数组),直接将delivery_categories字段设为对应的集合类型,移除自定义字符串转换器,此时JPA可以直接映射集合类型,In派生查询可以正常工作。
方案2:自定义查询使用字符串匹配函数
如果必须保留逗号拼接字符串的存储方式,放弃派生查询,自定义SQL使用数据库自带的字符串匹配函数处理:
以MySQL的FIND_IN_SET函数为例,示例代码如下:
@Query(nativeQuery = true, value = "SELECT * FROM 你的表名 " + "WHERE feedback_type = :feedbackType " + "AND valid_user_type = :userType " + "AND evaluation_type IN (:evaluationType) " + "AND status = :status " + "AND (FIND_IN_SET(:category, delivery_categories) > 0)") List<你的实体类> findMatchData(FeedbackType feedbackType, UserType userType, String category, List<EvaluationType> evaluationType, String status);
如果需要匹配多个配送分类,可动态拼接多个FIND_IN_SET条件用OR连接即可。
方案3:内存过滤(仅适合小数据量场景)
如果数据量很小,可以先查询满足其他条件的所有数据,再在业务层手动过滤deliveryCategories符合要求的记录,无需修改SQL逻辑。
内容的提问来源于stack exchange,提问作者Arsham Sedaghatbin
相关产品推荐
相关产品推荐

