diff --git a/CHANGELOG.md b/CHANGELOG.md
index d0e0810166..6142213b84 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,7 +22,8 @@
* 【core 】 修复`IoUtil`的`closeIfPosible`拼写错误,新建一个`closeIfPossible`方法,原方法标记deprecated(issue#4047@Github)
* 【http 】 修复`HttpRequest.sendRedirectIfPossible`未对308做判断问题。(issue#4053@Github)
* 【cron 】 修复`CronPatternUtil.nextDateAfter`当日为L时计算错误问题。(issue#4056@Github)
-* 【cron 】 修复`DialectRunner.count`方法中,去除包含多字段order by子句的SQL语句时错误问题(issue#4066@Github)
+* 【db 】 修复`NamedSql.replaceVar`关键字处理问题(issue#4062@Github)
+* 【db 】 修复`DialectRunner.count`方法中,去除包含多字段order by子句的SQL语句时错误问题(issue#4066@Github)
-------------------------------------------------------------------------------------------------------------
# 5.8.40(2025-08-26)
diff --git a/hutool-db/src/main/java/cn/hutool/db/sql/NamedSql.java b/hutool-db/src/main/java/cn/hutool/db/sql/NamedSql.java
index f060ae6c34..d8af4b028e 100644
--- a/hutool-db/src/main/java/cn/hutool/db/sql/NamedSql.java
+++ b/hutool-db/src/main/java/cn/hutool/db/sql/NamedSql.java
@@ -138,7 +138,7 @@ public class NamedSql {
if(paramMap.containsKey(nameStr)) {
// 有变量对应值(值可以为null),替换占位符为?,变量值放入相应index位置
final Object paramValue = paramMap.get(nameStr);
- if(ArrayUtil.isArray(paramValue) && StrUtil.containsIgnoreCase(sqlBuilder, "in")){
+ if(ArrayUtil.isArray(paramValue) && SqlUtil.isInClause(sqlBuilder)){
// 可能为select in (xxx)语句,则拆分参数为多个参数,变成in (?,?,?)
final int length = ArrayUtil.length(paramValue);
for (int i = 0; i < length; i++) {
diff --git a/hutool-db/src/main/java/cn/hutool/db/sql/SqlUtil.java b/hutool-db/src/main/java/cn/hutool/db/sql/SqlUtil.java
index ba35e4e992..ff9da9b79f 100644
--- a/hutool-db/src/main/java/cn/hutool/db/sql/SqlUtil.java
+++ b/hutool-db/src/main/java/cn/hutool/db/sql/SqlUtil.java
@@ -30,6 +30,10 @@ public class SqlUtil {
* 创建SQL中的order by语句的正则
*/
private static final Pattern PATTERN_ORDER_BY = PatternPool.get("(.*)\\s+order\\s+by\\s+[^\\s]+", Pattern.CASE_INSENSITIVE);
+ /**
+ * SQL中的in语句部分的正则
+ */
+ private static final Pattern PATTERN_IN_CLAUSE = PatternPool.get("\\s+in\\s+[(]", Pattern.CASE_INSENSITIVE);
/**
* 构件相等条件的where语句
@@ -268,4 +272,16 @@ public class SqlUtil {
// 去除order by 子句
return ReUtil.getGroup1(PATTERN_ORDER_BY, selectSql);
}
+
+ /**
+ * 判断当前上下文是否在 IN 子句中
+ * 通过检查变量前的SQL文本,判断是否符合 IN 子句的模式
+ *
+ * @param sql 当前已构建的SQL
+ * @return 是否在 IN 子句中
+ * @since 5.8.41
+ */
+ public static boolean isInClause(final CharSequence sql) {
+ return ReUtil.contains(PATTERN_IN_CLAUSE, sql);
+ }
}
diff --git a/hutool-db/src/test/java/cn/hutool/db/NamedSqlTest.java b/hutool-db/src/test/java/cn/hutool/db/NamedSqlTest.java
index dba29ae8f2..6ece77a89e 100644
--- a/hutool-db/src/test/java/cn/hutool/db/NamedSqlTest.java
+++ b/hutool-db/src/test/java/cn/hutool/db/NamedSqlTest.java
@@ -2,7 +2,6 @@ package cn.hutool.db;
import cn.hutool.core.map.MapUtil;
import cn.hutool.db.sql.NamedSql;
-import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import java.sql.SQLException;
@@ -10,6 +9,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import static org.junit.jupiter.api.Assertions.*;
+
public class NamedSqlTest {
@Test
@@ -100,4 +101,28 @@ public class NamedSqlTest {
query = Db.use().query(sql, new Object[]{paramMap});
assertEquals(1, query.size());
}
+
+ @Test
+ public void parseInTest2() {
+ // 测试表名包含"in"但不是IN子句的情况
+ final String sql = "select * from information where info_data = :info";
+ final HashMap paramMap = MapUtil.of("info", new int[]{10, 20});
+
+ final NamedSql namedSql = new NamedSql(sql, paramMap);
+ // sql语句不包含IN子句,不会展开数组
+ assertEquals("select * from information where info_data = ?", namedSql.getSql());
+ assertArrayEquals(new int[]{10, 20}, (int[]) namedSql.getParams()[0]);
+ }
+
+ @Test
+ public void parseInTest3() {
+ // 测试字符串中包含"in"关键字但不是IN子句的情况
+ final String sql = "select * from user where comment = 'include in text' and id = :id";
+ final HashMap paramMap = MapUtil.of("id", new int[]{5, 6});
+
+ final NamedSql namedSql = new NamedSql(sql, paramMap);
+ // sql语句不包含IN子句,不会展开数组
+ assertEquals("select * from user where comment = 'include in text' and id = ?", namedSql.getSql());
+ assertArrayEquals(new int[]{5, 6}, (int[]) namedSql.getParams()[0]);
+ }
}