如何在JDBI中使用@BindList结合MySQL的MATCH() AGAINST()函数
解决JDBI绑定列表到MATCH() AGAINST()的问题
核心需求
把原有的NOT IN查询替换为MATCH(request_id) AGAINST()的布尔模式匹配,实现批量排除指定request_id的功能,同时用JDBI安全绑定列表参数。
方案一:代码预处理生成匹配字符串(简单直接)
先在Java代码中将黑名单列表转换为符合MySQL布尔全文搜索格式的字符串,再通过@Bind绑定到SQL中:
- Java代码处理列表
import java.util.List; import java.util.stream.Collectors; // 假设黑名单ID列表 List<String> blacklistedRequestIds = List.of("req1", "req2", "req3"); // 转换为 "-req1 -req2 -req3" 格式 String searchClause = blacklistedRequestIds.stream() .map(id -> "-" + id) .collect(Collectors.joining(" "));
- JDBI查询注解
import org.jdbi.v3.sqlobject.customizer.Bind; import org.jdbi.v3.sqlobject.statement.SqlQuery; import java.util.List; public interface LogDao { @SqlQuery(""" SELECT * FROM bcsadmin_log WHERE MATCH(request_id) AGAINST(:searchClause IN BOOLEAN MODE) """) List<BcsadminLog> getLogsExcludingBlacklisted(@Bind("searchClause") String searchClause); }
方案二:用JDBI@BindList自定义转换(更优雅)
通过@BindList的elementConverter和separator属性,直接让JDBI处理列表元素的格式转换:
- 定义元素转换器
import org.jdbi.v3.core.argument.AttributeConverter; public class NegativeFulltextConverter implements AttributeConverter<String, String> { @Override public String convertToDatabaseColumn(String id) { // 给每个ID添加负号,用于布尔模式的排除匹配 return "-" + id; } @Override public String convertToEntityAttribute(String dbValue) { // 反向转换(查询结果映射时用,这里可选) return dbValue.substring(1); } }
- JDBI查询注解
import org.jdbi.v3.sqlobject.customizer.BindList; import org.jdbi.v3.sqlobject.statement.SqlQuery; import java.util.List; public interface LogDao { @SqlQuery(""" SELECT * FROM bcsadmin_log WHERE MATCH(request_id) AGAINST(:blacklistedRequestIds IN BOOLEAN MODE) """) List<BcsadminLog> getLogsExcludingBlacklisted( @BindList(value = "blacklistedRequestIds", elementConverter = NegativeFulltextConverter.class, separator = " ") List<String> blacklistedRequestIds ); }
注意事项
- 全文索引要求:
request_id字段必须创建全文索引,否则MATCH()函数会报错。创建索引的SQL示例:CREATE FULLTEXT INDEX idx_request_id ON bcsadmin_log(request_id); - 空列表处理:如果黑名单列表为空,
AGAINST('')会返回空结果,需要在代码中判断列表是否为空,若为空则执行无过滤的查询,或者在SQL中添加条件:
同时绑定列表大小参数SELECT * FROM bcsadmin_log WHERE (:blacklistedSize = 0 OR MATCH(request_id) AGAINST(:searchClause IN BOOLEAN MODE))@Bind("blacklistedSize") int blacklistedSize。 - 特殊字符转义:如果
request_id包含MySQL全文搜索的特殊字符(如+、-、(、)等),需要在转换器中添加转义逻辑,比如用\\转义特殊字符,避免匹配逻辑出错。
内容的提问来源于stack exchange,提问作者Kim Kakan Andersson
相关产品推荐
相关产品推荐

