3.4 预设 SQL(Key-SQL)
概念
预设 SQL 是将 SQL 语句预先定义好,通过唯一的 key 来调用。
优势:
- SQL 集中管理,便于维护
- 支持动态条件,灵活组装
- 可从数据库表统一加载(当前在初始化时读取,修改后需重新初始化才能通过公共 API 生效)
- 支持 SQL 嵌套复用
配置方式
方式一:XML 配置文件
# application.yml
dlz:
db:
sqllist: [app/*] # 预设 SQL 文件路径
在 resources/sql/app/ 下创建 SQL 文件:
<?xml version="1.0" encoding="UTF-8" ?>
<sqlList>
<!-- 基础查询 -->
<sql sqlId="key.user.findActive"><![CDATA[
SELECT * FROM user WHERE 1=1
[AND status = #{status}]
[AND name LIKE #{name}]
]]></sql>
<!-- SQL 嵌套 -->
<sql sqlId="key.condition.age"><![CDATA[
age > #{minAge} [AND age < #{maxAge}]
]]></sql>
<sql sqlId="key.user.findByAge"><![CDATA[
SELECT * FROM user WHERE 1=1
AND ${key.condition.age}
]]></sql>
</sqlList>
方式二:数据库配置
开启 use-db-sql 后,框架初始化时执行 dlz.db.sql 配置的查询;默认查询从 sys_sql.sql_key/sql_value 读取并别名为 k/s。例如可用项目自己的 Entity 或参数化 SQL 维护该表:
DB.jdbc.execute(
"INSERT INTO sys_sql (sql_key, sql_value) VALUES (?, ?)",
"user.findActive",
"SELECT * FROM user WHERE 1=1 [AND status = #{status}]");
SysSql 不是 DLZ-DB 公共模型;如果项目要使用 Entity 管理这张表,需自行定义。当前公共 API 也没有预设 SQL 热重载入口,不应宣称修改数据库记录后无需重启就会立即生效。
使用方式
// 基础查询
List<User> users = DB.sql.selectWrapper("key.user.findActive")
.addPara("status", 1)
.addPara("name", "张")
.queryList(User.class);
// 分页查询
Page<User> page = DB.sql.selectWrapper("key.user.findActive")
.addPara("status", 1)
.page(1, 10)
.queryPage(User.class);
// 数据库中的预设 SQL
DB.sql.selectWrapper("key.test.user.find")
.addPara("status", 1)
.queryList();
空值处理
方括号 [...] 内的条件:参数为空时自动忽略。
// status 有值,name 和 minAge 为空
DB.sql.selectWrapper("key.user.findActive")
.addPara("status", 1) // 有值,生效
.addPara("name", null) // 空值,忽略
.addPara("minAge", null) // 空值,忽略
.queryList(User.class);
// 生成 SQL:SELECT * FROM user WHERE 1=1 AND status = 1
规则
- XML 配置的
sqlId按原值存储,必须与 Java 调用使用的 key 一致;按当前规则应以"key."开头 - 数据库查询加载的
k值和DB.config.sql(...)参数可以不带"key.",这两个入口会自动补上前缀 - 支持 SQL 嵌套:
${key.xxx}引用并展开其他预设 SQL;这是 SQL 片段替换,不是#{参数名}参数绑定