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修复#
|
### Bug修复#
|
||||||
* 【core 】 修复原始类型转换时,转换失败没有抛出异常的问题
|
* 【core 】 修复原始类型转换时,转换失败没有抛出异常的问题
|
||||||
* 【core 】 修复BeanUtil.mapToBean中bean的class非空构造无法实例化问题
|
* 【core 】 修复BeanUtil.mapToBean中bean的class非空构造无法实例化问题
|
||||||
|
* 【core 】 修复NamedSql多个连续变量出现替换问题
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
package cn.hutool.db.sql;
|
package cn.hutool.db.sql;
|
||||||
|
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.text.StrBuilder;
|
import cn.hutool.core.text.StrBuilder;
|
||||||
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -12,8 +14,8 @@ import java.util.Map;
|
|||||||
* 支持的占位符格式为:
|
* 支持的占位符格式为:
|
||||||
* <pre>
|
* <pre>
|
||||||
* 1、:name
|
* 1、:name
|
||||||
* 2、?name
|
* 2、@name
|
||||||
* 3、@name
|
* 3、?name
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
@@ -21,6 +23,8 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public class NamedSql {
|
public class NamedSql {
|
||||||
|
|
||||||
|
private static final char[] NAME_START_CHARS = {':', '@', '?'};
|
||||||
|
|
||||||
private String sql;
|
private String sql;
|
||||||
private final List<Object> params;
|
private final List<Object> params;
|
||||||
|
|
||||||
@@ -69,6 +73,11 @@ public class NamedSql {
|
|||||||
* @param paramMap 名和参数的对应Map
|
* @param paramMap 名和参数的对应Map
|
||||||
*/
|
*/
|
||||||
private void parse(String namedSql, Map<String, Object> paramMap) {
|
private void parse(String namedSql, Map<String, Object> paramMap) {
|
||||||
|
if(MapUtil.isEmpty(paramMap)){
|
||||||
|
this.sql = namedSql;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int len = namedSql.length();
|
int len = namedSql.length();
|
||||||
|
|
||||||
final StrBuilder name = StrUtil.strBuilder();
|
final StrBuilder name = StrUtil.strBuilder();
|
||||||
@@ -77,18 +86,54 @@ public class NamedSql {
|
|||||||
Character nameStartChar = null;
|
Character nameStartChar = null;
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
c = namedSql.charAt(i);
|
c = namedSql.charAt(i);
|
||||||
if (c == ':' || c == '@' || c == '?') {
|
if (ArrayUtil.contains(NAME_START_CHARS, c)) {
|
||||||
nameStartChar = c;
|
nameStartChar = c;
|
||||||
|
|
||||||
|
// 新的变量开始符出现,要处理之前的变量
|
||||||
|
replaceVar(nameStartChar, name, sqlBuilder, paramMap);
|
||||||
} else if (null != nameStartChar) {
|
} else if (null != nameStartChar) {
|
||||||
// 变量状态
|
// 变量状态
|
||||||
if (isGenerateChar(c)) {
|
if (isGenerateChar(c)) {
|
||||||
// 变量名
|
// 变量名
|
||||||
name.append(c);
|
name.append(c);
|
||||||
} else {
|
} else {
|
||||||
|
// 非标准字符也非变量开始的字符出现表示变量名结束,开始替换
|
||||||
|
replaceVar(nameStartChar, name, sqlBuilder, paramMap);
|
||||||
|
nameStartChar = null;
|
||||||
|
sqlBuilder.append(c);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 变量以外的字符原样输出
|
||||||
|
sqlBuilder.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收尾,如果SQL末尾存在变量,处理之
|
||||||
|
if (false == name.isEmpty()) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
// 变量结束
|
// 变量结束
|
||||||
String nameStr = name.toString();
|
final String nameStr = name.toString();
|
||||||
if(paramMap.containsKey(nameStr)) {
|
if(paramMap.containsKey(nameStr)) {
|
||||||
// 有变量对应值(值可以为null),替换占位符
|
// 有变量对应值(值可以为null),替换占位符为?,变量值放入相应index位置
|
||||||
final Object paramValue = paramMap.get(nameStr);
|
final Object paramValue = paramMap.get(nameStr);
|
||||||
sqlBuilder.append('?');
|
sqlBuilder.append('?');
|
||||||
this.params.add(paramValue);
|
this.params.add(paramValue);
|
||||||
@@ -96,32 +141,11 @@ public class NamedSql {
|
|||||||
// 无变量对应值,原样输出
|
// 无变量对应值,原样输出
|
||||||
sqlBuilder.append(nameStartChar).append(name);
|
sqlBuilder.append(nameStartChar).append(name);
|
||||||
}
|
}
|
||||||
nameStartChar = null;
|
|
||||||
name.clear();
|
|
||||||
sqlBuilder.append(c);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sqlBuilder.append(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
name.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sql = sqlBuilder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否为标准的字符,包括大小写字母、下划线和数字
|
* 是否为标准的字符,包括大小写字母、下划线和数字
|
||||||
*
|
*
|
||||||
|
@@ -15,7 +15,11 @@ public class NamedSqlTest {
|
|||||||
public void parseTest() {
|
public void parseTest() {
|
||||||
String sql = "select * from table where id=@id and name = @name1 and nickName = :subName";
|
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);
|
NamedSql namedSql = new NamedSql(sql, paramMap);
|
||||||
//未指定参数原样输出
|
//未指定参数原样输出
|
||||||
@@ -28,7 +32,12 @@ public class NamedSqlTest {
|
|||||||
public void parseTest2() {
|
public void parseTest2() {
|
||||||
String sql = "select * from table where id=@id and name = @name1 and nickName = :subName";
|
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);
|
NamedSql namedSql = new NamedSql(sql, paramMap);
|
||||||
Assert.assertEquals("select * from table where id=? and name = ? and nickName = ?", namedSql.getSql());
|
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]);
|
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
|
@Test
|
||||||
public void queryTest() throws SQLException {
|
public void queryTest() throws SQLException {
|
||||||
Map<String, Object> paramMap = MapUtil
|
Map<String, Object> paramMap = MapUtil
|
||||||
|
Reference in New Issue
Block a user