跳到主要内容

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&lt;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&lt;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.TableDB.JdbcDB.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&lt;String, Object> data = new HashMap&lt;>();
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&lt;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 &lt; '2024-01-01')
// AND is_deleted = 0

3.4.3、逻辑删除

3.4.3.1 自动逻辑删除

当 Bean 中存在 isDeleted 字段时,DLZ-DB 自动:

  1. 删除时:UPDATE 设置删除标记,而非真正 DELETE
  2. 查询时:自动添加 is_deleted = 0 条件
  3. 更新时:自动添加 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(不会删全表)