sybn sybn-util 项目说明文档 - 基于java的跨数据库联合查询

关于变量占位符的说明

2020-06-02
sybn

简介

日常编写sql语句时, 经常用到变量占位符, 常用的有 ?, @val, #{val}, ${val} 等.

本工具类也支持上述变量占位符, 但与标准写法略有扩充和差异, 在此做专门的说明.

? 预编译占位符

? 占位符用于防注入传参, 仅在 sql 的某些特定位置有效, 标准用法如下:

query("select * from table where a > ?", 1);
query("select * from table where a in (?)", 1);

标准语法在 in 包含多个值时, 无法自适应 ? 占位符的数量. 因此在参数数量可变时, 使用起来很不方便.

本工具类扩展了 ? 的用法, 允许一个 ? 代指多个变量, 用法如下:

List<Integer> list = new ArrayList();
list.add(1);
list.add(2);
query("select * from table where a in (?)", list);
// 上述写法等效于下文
query("select * from table where a in (?, ?)", 1, 2);

此扩展特性适用于所有实现类, 比如 mongo, solr, es, hbase, csv 等.

@val 运行时变量

@val 占位符用于运行时计算的参数, 仅在 sql 的某些特定位置有效, 标准用法如下:

set @a := 1+1; -- 允许运算
select * from table where a = @a
-- 等效于
select * from table where a = 2

标准情况下变量只能是单一值, 无法存储数组.

本工具类扩展了变量的用法, 允许一个变量代指多个值, 用法如下:

set @a@list = [1,2]; -- 此时变量名必须以 @list 结尾
select * from table where a in (@a@list)
-- 上述写法等效于下文
select * from table where a in (1,2)

此特性适用于所有实现类, 比如 mongo, es, hbase 等.

#{val}, ${val} 预处理变量

#{val}, ${val} 占位符在 sql 被执行前替换 sql 的部分内容, 因此可以使用在sql的任何位置.

考虑防注入问题, 本工具类强制限制 #{val}, ${val} 的效果等于 MyBatis 的 #{val} 效果, 也就是任何非纯数字变量被替换时都会加’’. 实际效果如下:

Map<String, Object> param = new HashMap();
param.put("year", 2020); // 数字不会加引号
param.put("type", "2"); // 字符串会加引号
query("select * from table_#{year} where type = #{b}", param);
// 上述写法等效于下文
query("select * from table_2020 where type = '2'");

出于兼容性考虑, 当遇到 ${hiveconf:val} 时, 当作 ${val} 处理.

$${val} 预处理变量

有小伙伴希望保留 MyBatis 的 ${val} 效果, 允许直接替换 sql 内容.

考虑再三, 因为各种原因没敢开放此功能. 但是提供了一个中间方案.

参考的 @@val 作为全局变量的思路, 开放了 $${val} 全局变量, 此变量允许直接替换 sql, 绕过防注入限制, 但是只允许注入全局变量.

  • 关于全局变量

本工具包的全局变量无法使用 sql 修改, 必须去数据库中的全局变量表中定义.

首先要注册一个全局变量表, 支持使用 sql 表, mongo 表, List 作为全局变量表的载体.

// 将 ServerSettingDaoListImpl 注入到 ServerSettingUtil;
ServerSettingDaoListImpl.initServerSettingUtil();
// 将 MongoServerSettingDao 注入到 ServerSettingUtil;
// MongoServerSettingDao.initServerSettingUtil(conf);

// 将变量 aaa = test_table 写入全局变量, 也可以手动去数据库中定义全局变量
ServerSettingUtil.setStrValue("code_snippet_aaa", "test_table");

// 执行查询
query("select * from $${aaa} where type = '2'");
// 上述写法等效于下文
query("select * from test_table where type = '2'");

Similar Posts

Comments

暂不开放评论! 可微信联系