mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
fix bug
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
### Bug修复#
|
||||
* 【core 】 修复原始类型转换时,转换失败没有抛出异常的问题
|
||||
* 【core 】 修复BeanUtil.mapToBean中bean的class非空构造无法实例化问题
|
||||
* 【core 】 修复NamedSql多个连续变量出现替换问题
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
@@ -1,6 +1,8 @@
|
||||
package cn.hutool.db.sql;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.text.StrBuilder;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.util.LinkedList;
|
||||
@@ -12,8 +14,8 @@ import java.util.Map;
|
||||
* 支持的占位符格式为:
|
||||
* <pre>
|
||||
* 1、:name
|
||||
* 2、?name
|
||||
* 3、@name
|
||||
* 2、@name
|
||||
* 3、?name
|
||||
* </pre>
|
||||
*
|
||||
* @author looly
|
||||
@@ -21,6 +23,8 @@ import java.util.Map;
|
||||
*/
|
||||
public class NamedSql {
|
||||
|
||||
private static final char[] NAME_START_CHARS = {':', '@', '?'};
|
||||
|
||||
private String sql;
|
||||
private final List<Object> params;
|
||||
|
||||
@@ -69,6 +73,11 @@ public class NamedSql {
|
||||
* @param paramMap 名和参数的对应Map
|
||||
*/
|
||||
private void parse(String namedSql, Map<String, Object> paramMap) {
|
||||
if(MapUtil.isEmpty(paramMap)){
|
||||
this.sql = namedSql;
|
||||
return;
|
||||
}
|
||||
|
||||
int len = namedSql.length();
|
||||
|
||||
final StrBuilder name = StrUtil.strBuilder();
|
||||
@@ -77,51 +86,66 @@ public class NamedSql {
|
||||
Character nameStartChar = null;
|
||||
for (int i = 0; i < len; i++) {
|
||||
c = namedSql.charAt(i);
|
||||
if (c == ':' || c == '@' || c == '?') {
|
||||
if (ArrayUtil.contains(NAME_START_CHARS, c)) {
|
||||
nameStartChar = c;
|
||||
|
||||
// 新的变量开始符出现,要处理之前的变量
|
||||
replaceVar(nameStartChar, name, sqlBuilder, paramMap);
|
||||
} else if (null != nameStartChar) {
|
||||
// 变量状态
|
||||
if (isGenerateChar(c)) {
|
||||
// 变量名
|
||||
name.append(c);
|
||||
} else {
|
||||
// 变量结束
|
||||
String nameStr = name.toString();
|
||||
if(paramMap.containsKey(nameStr)) {
|
||||
// 有变量对应值(值可以为null),替换占位符
|
||||
final Object paramValue = paramMap.get(nameStr);
|
||||
sqlBuilder.append('?');
|
||||
this.params.add(paramValue);
|
||||
} else {
|
||||
// 无变量对应值,原样输出
|
||||
sqlBuilder.append(nameStartChar).append(name);
|
||||
}
|
||||
// 非标准字符也非变量开始的字符出现表示变量名结束,开始替换
|
||||
replaceVar(nameStartChar, name, sqlBuilder, paramMap);
|
||||
nameStartChar = null;
|
||||
name.clear();
|
||||
sqlBuilder.append(c);
|
||||
}
|
||||
} else {
|
||||
// 变量以外的字符原样输出
|
||||
sqlBuilder.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
// 收尾,如果SQL末尾存在变量,处理之
|
||||
if (false == name.isEmpty()) {
|
||||
// SQL结束依旧有变量名存在,说明变量位于末尾
|
||||
final Object paramValue = paramMap.get(name.toString());
|
||||
if (null != paramValue) {
|
||||
// 有变量对应值,替换占位符
|
||||
sqlBuilder.append('?');
|
||||
this.params.add(paramValue);
|
||||
} else {
|
||||
// 无变量对应值,原样输出
|
||||
sqlBuilder.append(nameStartChar).append(name);
|
||||
}
|
||||
name.clear();
|
||||
replaceVar(nameStartChar, name, sqlBuilder, paramMap);
|
||||
}
|
||||
|
||||
this.sql = sqlBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换变量,如果无变量,原样输出到SQL中去
|
||||
*
|
||||
* @param nameStartChar 变量开始字符
|
||||
* @param name 变量名
|
||||
* @param sqlBuilder 结果SQL缓存
|
||||
* @param paramMap 变量map(非空)
|
||||
*/
|
||||
private void replaceVar(Character nameStartChar, StrBuilder name, StrBuilder sqlBuilder, Map<String, Object> paramMap){
|
||||
if(name.isEmpty()){
|
||||
// 无变量,按照普通字符处理
|
||||
return;
|
||||
}
|
||||
|
||||
// 变量结束
|
||||
final String nameStr = name.toString();
|
||||
if(paramMap.containsKey(nameStr)) {
|
||||
// 有变量对应值(值可以为null),替换占位符为?,变量值放入相应index位置
|
||||
final Object paramValue = paramMap.get(nameStr);
|
||||
sqlBuilder.append('?');
|
||||
this.params.add(paramValue);
|
||||
} else {
|
||||
// 无变量对应值,原样输出
|
||||
sqlBuilder.append(nameStartChar).append(name);
|
||||
}
|
||||
|
||||
//清空变量,表示此变量处理结束
|
||||
name.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为标准的字符,包括大小写字母、下划线和数字
|
||||
*
|
||||
|
@@ -15,7 +15,11 @@ public class NamedSqlTest {
|
||||
public void parseTest() {
|
||||
String sql = "select * from table where id=@id and name = @name1 and nickName = :subName";
|
||||
|
||||
Map<String, Object> paramMap = MapUtil.builder("name1", (Object)"张三").put("age", 12).put("subName", "小豆豆").build();
|
||||
Map<String, Object> paramMap = MapUtil
|
||||
.builder("name1", (Object)"张三")
|
||||
.put("age", 12)
|
||||
.put("subName", "小豆豆")
|
||||
.build();
|
||||
|
||||
NamedSql namedSql = new NamedSql(sql, paramMap);
|
||||
//未指定参数原样输出
|
||||
@@ -28,7 +32,12 @@ public class NamedSqlTest {
|
||||
public void parseTest2() {
|
||||
String sql = "select * from table where id=@id and name = @name1 and nickName = :subName";
|
||||
|
||||
Map<String, Object> paramMap = MapUtil.builder("name1", (Object)"张三").put("age", 12).put("subName", "小豆豆").put("id", null).build();
|
||||
Map<String, Object> paramMap = MapUtil
|
||||
.builder("name1", (Object)"张三")
|
||||
.put("age", 12)
|
||||
.put("subName", "小豆豆")
|
||||
.put("id", null)
|
||||
.build();
|
||||
|
||||
NamedSql namedSql = new NamedSql(sql, paramMap);
|
||||
Assert.assertEquals("select * from table where id=? and name = ? and nickName = ?", namedSql.getSql());
|
||||
@@ -38,6 +47,19 @@ public class NamedSqlTest {
|
||||
Assert.assertEquals("小豆豆", namedSql.getParams()[2]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseTest3() {
|
||||
// 测试连续变量名出现是否有问题
|
||||
String sql = "SELECT to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') as sysdate FROM dual";
|
||||
|
||||
Map<String, Object> paramMap = MapUtil
|
||||
.builder("name1", (Object)"张三")
|
||||
.build();
|
||||
|
||||
NamedSql namedSql = new NamedSql(sql, paramMap);
|
||||
Assert.assertEquals(sql, namedSql.getSql());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryTest() throws SQLException {
|
||||
Map<String, Object> paramMap = MapUtil
|
||||
|
Reference in New Issue
Block a user