03 - 基础操作
3.1 查询操作
3.1.1、Pojo查询(推荐)
3.1.1.1 查询单条记录
// 方式1:返回 Bean
User user = DB.Pojo.select(User.class)
.eq(User::getId, 1)
.queryBean();
// 方式2:返回 ResultMap
ResultMap result = DB.Pojo.select(User.class)
.eq(User::getId, 1)
.queryOne();
3.1.1.2 查询列表
// 查询全部
List<User> all = DB.Pojo.select(User.class).queryBeanList();
// 条件查询
List<User> users = DB.Pojo.select(User.class)
.eq(User::getStatus, 1)
.gt(User::getAge, 18)
.orderByDesc(User::getCreateTime)
.queryBeanList();
3.1.1.3 查询数量
long count = DB.Pojo.select(User.class)
.eq(User::getStatus, 1)
.count();
3.1.1.4 查询指定字段
List<User> users = DB.Pojo.select(User.class)
.select(User::getId, User::getName, User::getAge)
.eq(User::getStatus, 1)
.queryBeanList();
// 生成 SQL:SELECT id, name, age FROM user WHERE status = 1
3.1.1.5 查询字段
List<String> cities = DB.Pojo.select(User.class)
.select(User::getCity)
.queryStrList(String.class);
String citie = DB.Pojo.select(User.class)
.select(User::getCity)
.eq(User::getId,1)
.queryStr(String.class);
3.1.2、Table查询(表名方式)
3.1.2.1 基础查询
// 查询单条
ResultMap result = DB.Table.select("user")
.eq("id", 1)
.queryOne();
// 查询单条
User user = DB.Table.select("user")
.eq("id", 1)
.queryOne(User.class);
// 查询列表
List<ResultMap> list = DB.Table.select("user")
.eq("status", 1)
.queryList();
// 转换为 Bean
List<User> users = DB.Table.select("user")
.eq("status", 1)
.queryList(User.class);
3.1.2.2 动态表名
String tableName = "user_" + year; // 如 user_2024
List<ResultMap> list = DB.Table.select(tableName)
.eq("status", 1)
.queryList();
3.1.3、原生 SQL 查询
3.1.3.1 使用占位符 ?
// 单个结果:ResultMap
ResultMap result = DB.Jdbc.select("select * from user where id = ?",1)
.queryOne();
// 单个结果:User
User user = DB.Jdbc.select("select * from user where id = ?",1)
.queryOne(User.class);
// 列表结果
List<ResultMap> list = DB.Jdbc.select(
"SELECT * FROM user WHERE status = ? AND age > ?",
1, 18
).queryList();
// 单个值
String name = DB.Jdbc.select(
"SELECT name FROM user WHERE id = ?",
1
).queryStr();
// 值列表
List<Long> ids = DB.Jdbc.select(
"SELECT id FROM user WHERE status = ?",
1
).queryLongList();
3.1.3.2 复杂查询
//sql 预设到xml:key.user.getUserWithDept
String sql = """
SELECT u.*, d.name as dept_name
FROM user u
LEFT JOIN department d ON u.dept_id = d.id
WHERE u.status = ? AND d.type = ?
ORDER BY u.create_time DESC
""";
List<ResultMap> list = DB.Jdbc.select(sql, 1, "tech").queryList();
3.1.4、预设 SQL 查询
3.1.4.1 基础使用
<sql sqlId="key.user.getUserWithDept"><![CDATA[
SELECT u.*, d.name as dept_name
FROM user u
LEFT JOIN department d ON u.dept_id = d.id
WHERE 1=1
[and u.status = #{status}]
[AND d.type = #{type}]
]]></sql>
//sql 预设到xml:key.user.getUserWithDept
List<ResultMap> list = DB.Sql.select("key.user.getUserWithDept")
.para("status", 1)
.para("type", "tech")
.queryList();
详见「第八章:预设 SQL」
3.1.5、结果处理
3.1.5.1 返回类型
| 方法 | 返回类型 | 说明 |
|---|---|---|
.queryBean() | Bean / null | 单条记录,无则返回 null |
.queryOne() | ResultMap / null | 单条记录,Map 形式 |
.queryBeanList() | List<Bean> | 列表 |
.queryList() | List<ResultMap> | 列表,Map 形式 |
.count() | long | 数量 |
.queryBeanPage() | Page<Bean> | 分页结果 |
.queryPage() | Page<ResultMap> | 分页结果,Map 形式 |
3.1.5.2 ResultMap 深度取值
ResultMap result = DB.Table.select("user")
.eq("id", 1)
.queryOne();
// 基础取值
String name = result.getStr("name");
Integer age = result.getInt("age", 0); // 带默认值
// 深度取值(假设有嵌套 JSON 字段)
String city = result.getStr("address.city", "未知");
List<Order> orders = result.getList("orders", Order.class);
// 负数索引
String lastTag = result.getStr("tags[-1]"); // 最后一个标签
3.2 插入操作
3.2.1、Wrapper 插入(推荐)
3.2.1.1 基础插入
User user = new User();
user.setName("张三");
user.setAge(25);
user.setEmail("zhangsan@example.com");
// 插入
DB.Pojo.insert(user); // Pojo 插入后自动回填主键到 user 对象
Long id = user.getId(); // 从 user 对象获取回填的主键
System.out.println("新用户 ID:" + id);
⚠️ 主键回填说明:
- 只有
DB.Pojo.insert()插入后会自动回填主键到 Bean 对象 DB.Table、DB.Jdbc、DB.Sql等方法不会回填主键,需要通过返回值获取
3.2.1.2 插入非空字段
User user = new User();
user.setName("张三");
// age 和 email 为 null,不会插入
DB.Pojo.insert(user);
// 生成 SQL:INSERT INTO user (name) VALUES ('张三')
3.2.2、Maker 插入(表名方式)
3.2.2.1 基础插入
DB.Pojo.insert("user")
.value("name", "张三")
.value("age", 25)
.value("email", "zhangsan@example.com")
.value("create_time", new Date())
.execute();
3.2.2.2 使用 Map 插入
Map<String, Object> data = new HashMap<>();
data.put("name", "张三");
data.put("age", 25);
data.put("email", "zhangsan@example.com");
DB.Table.insert("user").value(data).execute();
3.2.2.3 返回自增主键
Long id = DB.Table.insert("user")
.value("name", "张三")
.value("age", 25)
.insertWithAutoKey();
3.2.3、批量插入
3.2.3.1 批量插入 Bean 列表
List<User> users = Arrays.asList(
new User("张三", 25),
new User("李四", 30),
new User("王五", 28)
);
DB.Batch.insert(users);
DB.Batch.insert(users,100);//每个批次100条
3.2.4、插入或更新
3.2.4.1 存在则更新,不存在则插入
User user = new User();
user.setId(1L); // 主键
user.setName("张三");
user.setAge(26);
DB.Pojo.insertOrUpdate(user);
// 如果 id=1 存在 → UPDATE
// 如果 id=1 不存在 → INSERT
3.3 更新操作
3.3.1、Wrapper 更新(推荐)
3.3.1.1 根据条件更新
User user = new User();
user.setName("李四");
user.setAge(30);
DB.Pojo.updateById(user);
// 生成 SQL:
// UPDATE user SET name='李四', age=30
// WHERE id = 1 AND is_deleted = 0
3.3.1.2 更新指定字段
DB.Pojo.update(User.class)
.set(User::getName, "李四")
.set(User::getUpdateTime, new Date())
.eq(User::getId, 1)
.execute();
3.3.1.3 条件更新
DB.Pojo.update(User.class)
.set(User::getStatus, 0)
.eq(User::getType, 1)
.lt(User::getLastLoginTime, DateUtil.addDays(new Date(), -30))
.execute();
// 将 30 天未登录的用户设为禁用
3.3.2、Maker 更新(表名方式)
3.3.2.1 基础更新
DB.Table.update("user")
.set("name", "李四")
.set("update_time", new Date())
.where(Condition.where()
.eq("id", 1)
)
.execute();
3.3.2.2 复杂条件更新
DB.Table.update("user")
.set("status", 1)
.where(Condition.where()
.eq("type", 1)
.and(w -> w
.eq("level", 3)
.gt("score", 100)
)
.or(w -> w
.eq("vip", 1)
)
)
.execute();
// 生成 SQL:
// UPDATE user SET status = 1
// WHERE type = 1
// AND (level = 3 AND score > 100)
// OR (vip = 1)
// AND is_deleted = 0
3.3.2.3 表达式更新
// 数值增减
DB.Table.update("user")
.setSql("score = score + 10")
.setSql("login_count = login_count + 1")
.eq("id", 1)
.execute();
// 生成 SQL:
// UPDATE user SET score = score + 10, login_count = login_count + 1
// WHERE id = 1
3.3.3、安全机制
3.3.3.1 必须有条件
// ❌ 无条件更新会被拦截或添加安全条件
DB.Pojo.update(User.class)
.set(User::getStatus, 0)
.execute();
// 生成 SQL(自动添加 is_deleted 条件):
// UPDATE user SET status = 0 WHERE is_deleted = 0
// 不会更新全表!
3.3.32 逻辑删除自动添加
// Bean 有 isDeleted 字段时,自动添加条件
DB.Pojo.update(user).eq(User::getId, 1).execute();
// 生成 SQL:
// UPDATE user SET ... WHERE id = 1 AND is_deleted = 0
3.4 删除操作
3.4.1、Wrapper 删除(推荐)
3.4.1.1 条件删除
DB.Pojo.delete(User.class)
.eq(User::getId, 1)
.execute();
// 生成 SQL(逻辑删除):
// UPDATE user SET is_deleted = 1 WHERE id = 1 AND is_deleted = 0
// 或(物理删除):
// DELETE FROM user WHERE id = 1 AND is_deleted = 0
3.4.1.2 复杂条件删除
DB.Pojo.delete(User.class)
.eq(User::getStatus, 0)
.lt(User::getCreateTime, DateUtil.addDays(new Date(), -365))
.execute();
// 删除一年前已禁用的用户
3.4.2、Maker 删除(表名方式)
3.4.2.1 基础删除
DB.Table.delete("user")
.eq("id", 1)
.execute();
3.4.2.2 复杂条件删除
Condition where = Condition.where()
.eq("status", 0)
.and(w -> w.eq("type", 1).eq("level", 0))
.or(w -> w.lt("expire_time", new Date()));
DB.Table.delete("user").where(where).execute();
// 生成 SQL:
// DELETE FROM user
// WHERE status = 0
// AND (type = 1 AND level = 0)
// OR (expire_time < '2024-01-01')
// AND is_deleted = 0
3.4.3、逻辑删除
3.4.3.1 自动逻辑删除
当 Bean 中存在 isDeleted 字段时,DLZ-DB 自动:
- 删除时:UPDATE 设置删除标记,而非真正 DELETE
- 查询时:自动添加
is_deleted = 0条件 - 更新时:自动添加
is_deleted = 0条件
// 执行删除
DB.Pojo.delete(User.class).eq(User::getId, 1).execute();
// 实际执行的 SQL:
// UPDATE user SET is_deleted = 1 WHERE id = 1 AND is_deleted = 0
3.4.3.2 配置逻辑删除
dlz:
db:
# 逻辑删除字段名
logic-delete-field: is_deleted
3.4.3.3 物理删除
// 如果确实需要物理删除
DB.Pojo.deletePhysical(User.class)
.eq(User::getId, 1)
.execute();
// 执行真正的 DELETE FROM user WHERE id = 1
3.4.3、安全机制
3.4.4.1 无条件删除保护
// ❌ 无条件删除会被安全处理
DB.Pojo.delete(User.class).execute();
// 生成 SQL(只会删除逻辑未删除的):
// DELETE FROM user WHERE is_deleted = 0
// 而不是 DELETE FROM user(不会删全表)