📖 # DLZ-DB - 速查文档
目录
- 2.1 基础条件
- 2.2 范围查询(IN,between查询)(多种写法)
- 2.3 模糊检索
- 2.3 OR / AND 嵌套条件
- 2.4 复杂嵌套示例
- 2.5 自定义 SQL 片段 (Apply/Sql)
- 2.6 空值自动忽略
一、查询操作
1.1 基于 Bean 的查询(推荐)
// 查询单条
User user = DB.Pojo.select(User.class)
.eq(User::getId, 1)
.queryBean();
// 查询列表
List<User> users = DB.Pojo.select(User.class)
.eq(User::getStatus, 1)
.queryBeanList();
// 查询数量
long count = DB.Pojo.select(User.class)
.eq(User::getStatus, 1)
.count();
1.2 基于表名的查询
// 返回 ResultMap(继承自 JSONMap,支持深度取值)
ResultMap result = DB.Table.select("sys_user")
.eq("status", 1)
.queryOne();
// 取值
String name = result.getStr("name");
Integer age = result.getInt("profile.age", 0);
1.3 原生 JDBC 查询
// 使用 ? 占位符
JdbcQuery query = DB.Jdbc.select(
"SELECT * FROM user WHERE status = ? AND age > ?",
1, 18
);
// 获取结果
List<ResultMap> list = query.queryList();
String value = query.queryStr();
1.4 预设 SQL 查询(key-sql)
// 通过 key 获取预设的 SQL(支持在数据库中在线编辑)
SqlQuery query = DB.Sql.select("user.findByCondition");
query.addPara("status", 1);
query.addPara("name", "张三");
query.setPage(Page.build(1, 10));
List<User> users = query.queryList(User.class);
二、条件构造器
条件方法一览
| 方法 | 说明 | 示例 |
|---|---|---|
isn(字段) | 为空 | column IS NULL |
isnn(字段) | 不为空 | column IS NOT NULL |
eq(字段, 值) | 等于 | column = ? |
ne(字段, 值) | 不等于 | column <> ? |
gt(字段, 值) | 大于 | column > ? |
ge(字段, 值) | 大于等于 | column >= ? |
lt(字段, 值) | 小于 | column < ? |
le(字段, 值) | 小于等于 | column <= ? |
in(字段, 值列表) | 在列表中 | column IN (val1, val2, ...) |
ni(字段, 值列表) | 不在列表中 | column NOT IN (val1, val2, ...) |
lk(字段, 值) | 模糊匹配 | column LIKE ? (值会被加上%) |
ll(字段, 值) | 左模糊匹配 | column LIKE ? (值后加%) |
lr(字段, 值) | 右模糊匹配 | column LIKE ? (值前加%) |
nl(字段, 值) | 非模糊匹配 | column NOT LIKE ? (值前后加%) |
bt(字段, 值1, 值2) | 范围查询 | column BETWEEN ? AND ? |
nb(字段, 值1, 值2) | 非范围查询 | column NOT BETWEEN ? AND ? |
2.1 基础条件
DB.Pojo.select(User.class)
// 基础比较操作
.eq(User::getStatus, 1) // status = 1
.ne(User::getType, 0) // type <> 0
.gt(User::getAge, 18) // age > 18
.ge(User::getScore, 60) // score >= 60
.lt(User::getLevel, 10) // level < 10
.le(User::getRetryCount, 3) // retry_count <= 3
// 空值检查
.isn(User::getDeleteTime) // delete_time IS NULL
.isnn(User::getEmail) // email IS NOT NULL
.queryBeanList();
2.2 范围查询(IN,between查询)(多种写法)
DB.Pojo.select(User.class)
// 方式1:逗号分隔的字符串
.in(User::getId, "1,2,3,4,5") // id IN (1,2,3,4,5)
// 方式2:逗号分割的字符串
.in(User::getCode, "A,B,C") //code IN ('A','B','C')
// 方式3:子查询
.in(User::getId, new Integer[]{1, 2, 3, 4, 5}) // id IN (1,2,3,4,5)
// 方式4:子查询
.in(User::getDeptId, "sql:SELECT id FROM dept WHERE status = 1") //dept_id IN (SELECT id FROM dept WHERE status = 1)
// not in
.ni(User::getName, "admin,root") // name NOT IN ('admin','root')
//between
.bt(User::getAge, 18, 30) //AGE between 18 and 30
.bt(User::getAge, Arrays.asList(18, 30))//AGE between 18 and 30
.bt(User::getAge, new Integer[]{18,30})//AGE between 18 and 30
.bt(User::getAge, "18","30")//AGE between '18' and '30'
.bt(User::getAge, "18,30")//AGE between '18' and '30'
.bt(User::getAge, new String[]{"18","30"})//AGE between '18' and '30'
.bt(User::getCreateTime, DateUtil.getDate("2020-01-01"), DateUtil.getDate("2020-01-01"))//CREATE_TIME between '2020-01-01 00:00:00' and '2021-01-01 00:00:00'
//not between
.nb(User::getScore, 0, 60) //SCORE not between 0 and 60
.queryBeanList();
2.3 模糊检索
DB.Pojo.select(User.class)
.lk(User::getName, "张") // name LIKE '%张%' (模糊匹配)
.ll(User::getPhone, "138") // phone LIKE '138%' (左模糊匹配)
.lr(User::getAddress, "北京") // address LIKE '%北京' (右模糊匹配)
.nl(User::getDescription, "测试") // description NOT LIKE '%测试%' (非模糊匹配)
.queryBeanList();
2.3 OR / AND 嵌套条件
// 场景:查询 (status=1) AND (name='张三' OR age>20)
DB.Pojo.select(User.class)
.eq(User::getStatus, 1)
.or(w -> w
.eq(User::getName, "张三")
.gt(User::getAge, 20)
)
.queryBeanList();
// 场景:查询 (type=1 OR type=2) AND (status=1 AND level>3)
DB.Pojo.select(User.class)
.or(w -> w
.eq(User::getType, 1)
.eq(User::getType, 2)
)
.and(w -> w
.eq(User::getStatus, 1)
.gt(User::getLevel, 3)
)
.queryBeanList();
2.4 复杂嵌套示例
// 场景:校验菜单编码或名称是否重复(排除自己)
Menu menu = new Menu();
menu.setId(100L);
menu.setCode("qsm");
menu.setName("测试");
DB.Pojo.select(Menu.class)
//条件判断,如果id不为空,则添加条件
.ne(menu.getId() != null,Menu::getId, menu.getId())
// 编码相同 OR (名称相同 AND 分类为1)
.or(w -> w
.eq(Menu::getCode, menu.getCode())
.and(s -> s
.eq(Menu::getName, menu.getName())
.eq(Menu::getCategory, "1")
)
)
.queryList();
// 生成的 SQL:
// SELECT * FROM sys_menu
// WHERE ID <> 100
// AND (CODE = 'qsm' OR (NAME = '测试' AND CATEGORY = '1'))
// AND IS_DELETED = 0
2.5 自定义 SQL 片段 (Apply/Sql)
// 使用 sql + JSONMap 参数
DB.Pojo.select(User.class)
.eq(User::getStatus, 1)
.sql("id IN (SELECT user_id FROM order WHERE amount > #{amount})", new JSONMap("amount", 1000))
.queryBeanList();
// EXISTS 查询
DB.Pojo.select(User.class)
.eq(User::getStatus, 1)
.sql("EXISTS (SELECT 1 FROM vip WHERE user_id = t.id AND level >= #{level})",
new JSONMap("level", 3))
.queryBeanList();
2.6 空值自动忽略
// 当参数为空时,条件自动忽略,不会报错
String name = null; // 前端没传
DB.Table.delete("user")
.sql("[name = #{name}]", new JSONMap("name", name)) // 方括号表示:空值时忽略此条件
.execute();
// name 为空时生成:DELETE FROM user WHERE IS_DELETED = 0
// name 有值时生成:DELETE FROM user WHERE (name = 'xxx') AND IS_DELETED = 0
三、分页与排序
3.1 分页查询
// 基础分页
Page<User> page = DB.Pojo.select(User.class)
.eq(User::getStatus, 1)
.page(Page.build(1, 10)) // 第1页,每页10条
.queryBeanPage();
// 获取数据
List<User> records = page.getRecords();
long total = page.getTotal();
3.2 排序
// 单字段排序
DB.Jdbc.select("SELECT * FROM user WHERE status = ?", 1)
.page(Page.build(1, 10, Order.desc("create_time")))
.queryList();
// 多字段排序
DB.Jdbc.select("SELECT * FROM user")
.page(Page.build(1, 10, Order.descs("create_time", "id")))
.queryList();
// 混合排序
DB.Jdbc.select("SELECT * FROM user")
.page(Page.build(Order.asc("status"), Order.desc("create_time")))
.queryList();
四、插入操作
4.1 Bean 插入
User user = new User();
user.setName("张三");
user.setAge(25);
// 普通插入
DB.Pojo.insert(user); // Pojo 插入后自动回填主键到 user 对象
Long id = user.getId(); // 从 user 对象获取回填的主键
4.2 指定表名插入
DB.Table.insert("sys_user")
.set("name", "张三")
.set("age", 25)
.set("create_time", new Date())
.execute();
五、更新操作
5.1 Bean 更新
User user = new User();
user.setId(1L);
user.setName("李四");
user.setAge(30);
// 根据 ID 更新非空字段
DB.Pojo.updateById(user);
5.2 指定表名更新
DB.Table.update("sys_user")
.set("name", "李四")
.set("update_time", new Date())
.where(Condition.where()
.eq("id", 1)
.eq("status", 1)
)
.execute();
5.3 复杂条件更新
DB.Table.update("sys_config")
.set("value", "new_value")
.where(Condition.where()
.eq("type", 1)
.and(w -> w
.eq("category", "A")
.eq("status", 1)
)
.or(w -> w
.eq("category", "B")
.gt("priority", 5)
)
)
.execute();
六、删除操作
6.1 Bean 删除(自动逻辑删除)
// 当 Bean 有 isDeleted 字段时,自动添加逻辑删除条件
DB.Pojo.delete(User.class)
.eq(User::getId, 1)
.execute();
// 生成的 SQL:
// DELETE FROM user WHERE id = 1 AND IS_DELETED = 0
6.2 条件删除
DB.Table.delete("sys_log")
.where(Condition.where()
.lt("create_time", DateUtil.addDays(new Date(), -30))
.eq("status", 0)
)
.execute();
6.3 安全机制:无条件删除更新保护
// 未指定条件时,删除条件自动设置false,(防止条件有误全表删除)
DB.Pojo.delete(User.class).execute();
// 生成的 SQL:
// delete from USER where false
// 未指定条件时,更新条件自动设置为false,(防止条件有误造成全表更新)
DB.Pojo.update(User.class).set("status", 1).execute();
// 生成的 SQL:
// update user set status =1 where false
七、预设 SQL(Key-SQL)
支持将 SQL 预设在配置文件或数据库中,通过 key 调用
7.1 配置预设 SQL
sql文件配置
<?xml version="1.0" encoding="UTF-8" ?>
<sqlList>
<!--
测试4_6_2
-->
<sql sqlId="key.conditionTest4_6_2"><![CDATA[
age > #{minAge} [AND age < #{maxAge}]
]]></sql>
<!--
测试5_1_4
-->
<sql sqlId="key.pageAndOrderTest5_1_4"><![CDATA[
SELECT * FROM user WHERE and status = #{status}
]]></sql>
<!--
测试5_1_4
-->
<sql sqlId="key.test.user.findActive"><![CDATA[
SELECT * FROM user WHERE 1=1 [and status = #{status}]
]]></sql>
<sql sqlId="key.test.user.find"><![CDATA[
SELECT * FROM user WHERE 1=1
[and name like #{name}]
[and age > #{minAge}]
]]></sql>
<sql sqlId="key.test.user.find2"><![CDATA[
SELECT * FROM user WHERE 1=1
[and name like #{name}]
[and age > #{minAge}]
[and #{key.conditionTest4_6_2}]
]]></sql>
</sqlList>
DB配置
//添加sql到数据库中。sqlKey必须唯一,不用添加"key."开头
SysSql sysSql = new SysSql();
sysSql.setSqlKey("test.user.findActive");
sysSql.setSqlValue("SELECT * FROM user WHERE 1=1 [and status = #{status}]");
DB.Pojo.insert(sysSql);
//使用sql。所有预设sql的key都是"key."开头
DB.Sql.select("key.test.user.findActive").addPara("status", 1).queryList();
7.2 使用预设 SQL
// 方括号内的条件:参数为空时自动忽略
SqlQuery query = DB.Sql.select("key.test.user.find");
query.addPara("name", "张"); // 有值,条件生效
query.addPara("minAge", null); // 空值,条件忽略
query.setPage(Page.build(1, 10, Order.asc("id")));
List<User> users = query.queryList(User.class);
// 生成的 SQL:
// SELECT * FROM user WHERE status = 1 AND name LIKE '张'
// ORDER BY id ASC LIMIT 0,10
7.3 预设 SQL 嵌套
// 支持在预设 SQL 中引用其他预设 SQL
// key.test.user.find2 中 #{key.conditionTest4_6_2} 会被替换为另一个预设 SQL 的内容
//最终结果为
"""
SELECT * FROM user WHERE 1=1
[and name like #{name}]
[and age > #{minAge}]
[age > #{minAge} [AND age < #{maxAge}]]
"""
🔧 高级特性
多数据源支持
// 切换数据源
DB.Dynamic.use("test",()-> {
return DB.Pojo.select(SysSql.class).eq("id", "1").queryBean();
});
DB.Dynamic.use("default",()-> {
return DB.Pojo.select(SysSql.class).eq("id", "1").queryBean();
});
事务控制
支持spring 事务控制,可在service中使用@Transactional注解
@Transactional
public void transfer(Long fromId, Long toId, BigDecimal amount) {
DB.Pojo.update(Account.class)
.setSql("balance = balance - #{amount}", Params.of("amount", amount))
.eq(Account::getId, fromId)
.execute();
DB.Pojo.update(Account.class)
.setSql("balance = balance + #{amount}", Params.of("amount", amount))
.eq(Account::getId, toId)
.execute();
}
多数据源结合事务控制
DB.Dynamic.use("default",true,()-> {
return DB.Pojo.select(SysSql.class).eq("id", "1").queryBean();
});
SQL 注入防护
// ✅ 安全:使用 #{} 参数化查询
DB.Table.select("user")
.sql("name = #{name}", new JSONMap("name", userInput))
.queryList();
// ✅ 安全:使用 ? 占位符
DB.Jdbc.select("SELECT * FROM user WHERE name = ?", userInput);
// ⚠️ 注意:${} 是直接替换,需确保来源安全
📋 API 参考
DB 类 API
所有数据库操作的统一入口
查询方法
| 方法 | 返回类型 | 说明 |
|---|---|---|
query(Class<T>) | PojoQuery<T> | Bean 查询 |
query(String tableName) | MakerSelect | 表名查询 |
jdbcSelect(String sql, Object... args) | JdbcQuery | 原生 SQL 查询 |
sqlSelect(String key) | SqlQuery | 预设 SQL 查询 |
插入方法
| 方法 | 返回类型 | 说明 |
|---|---|---|
insert(T bean) | WrapperInsert<T> | Bean 插入 |
insert(String tableName) | MakerInsert | 表名插入 |
insertBatch(List<T>) | BatchInsert<T> | 批量插入 |
更新方法
| 方法 | 返回类型 | 说明 |
|---|---|---|
update(T bean) | WrapperUpdate<T> | Bean 更新 |
update(String tableName) | MakerUpdate | 表名更新 |
删除方法
| 方法 | 返回类型 | 说明 |
|---|---|---|
delete(Class<T>) | WrapperDelete<T> | Bean 删除 |
delete(String tableName) | MakerDelete | 表名删除 |
其他方法
| 方法 | 说明 |
|---|---|
use(String datasource) | 切换数据源 |
Wrapper 类 API
PojoQuery<T> 查询方法
条件方法
| 方法 | 说明 |
|---|---|
eq(字段, 值) | 等于 |
ne(字段, 值) | 不等于 |
gt(字段, 值) | 大于 |
ge(字段, 值) | 大于等于 |
lt(字段, 值) | 小于 |
le(字段, 值) | 小于等于 |
like(字段, 值) | LIKE %值% |
likeLeft(字段, 值) | LIKE %值 |
likeRight(字段, 值) | LIKE 值% |
in(字段, 值) | IN |
notIn(字段, 值) | NOT IN |
between(字段, 值1, 值2) | BETWEEN |
isNull(字段) | IS NULL |
isNotNull(字段) | IS NOT NULL |
or(Consumer) | OR 条件 |
and(Consumer) | AND 条件 |
apply(sql, args) | 自定义 SQL |
sql(sql, params) | 自定义 SQL |
结果方法
| 方法 | 返回类型 | 说明 |
|---|---|---|
queryBean() | T | 单条 Bean |
queryOne() | ResultMap | 单条 Map |
queryBeanList() | List<T> | 列表 |
queryList() | List<ResultMap> | Map 列表 |
count() | long | 数量 |
queryBeanPage() | Page<T> | 分页结果 |
queryPage() | Page<ResultMap> | 分页结果,Map 形式 |
其他方法
| 方法 | 说明 |
|---|---|
select(字段...) | 指定查询字段 |
orderByAsc(字段) | 升序排序 |
orderByDesc(字段) | 降序排序 |
page(Page) | 设置分页 |
Condition 类 API
独立的条件构造器,可复用
创建
Condition condition = Condition.where();
方法
与 Wrapper 相同,支持所有条件方法:
eq,ne,gt,ge,lt,lelike,likeLeft,likeRightin,notIn,betweenisNull,isNotNullor,andapply,sql
使用
Condition condition = Condition.where()
.eq("status", 1)
.gt("age", 18);
// 应用到查询
DB.Table.select("user").where(condition).queryList();
// 应用到更新
DB.Table.update("user").set("flag", 1).where(condition).execute();
// 应用到删除
DB.Table.delete("user").where(condition).execute();
Page 类 API
创建分页参数
// 基础分页
Page.build(页码, 每页条数)
// 带排序
Page.build(页码, 每页条数, Order...)
// 仅排序
Page.build(Order...)
Order 排序
Order.asc("字段") // 升序
Order.desc("字段") // 降序
Order.ascs("字段"...) // 多字段升序
Order.descs("字段"...) // 多字段降序
分页结果
| 方法 | 返回类型 | 说明 |
|---|---|---|
getRecords() | List<T> | 当前页数据 |
getTotal() | long | 总条数 |
getPages() | int | 总页数 |
getCurrent() | int | 当前页码 |
getSize() | int | 每页条数 |
hasNext() | boolean | 是否有下一页 |
hasPrevious() | boolean | 是否有上一页 |