跳到主要内容

06 - 结果映射

6.1 Bean 映射

自动映射规则

DLZ-DB 自动将数据库字段映射到 Bean 属性:

数据库字段Bean 属性说明
user_nameuserName下划线转驼峰
USER_NAMEuserName大写下划线转驼峰
usernameusername直接匹配

定义实体类

@Data
@Table("sys_user") // 指定表名(可选)
public class User {

private Long id;

private String userName; // 对应 user_name

private Integer age;

@Column("email_address") // 指定列名
private String email;

private Date createTime; // 对应 create_time

@Ignore // 忽略此字段,不映射
private String tempData;
}

查询映射

// 单条映射
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();

// 原生 SQL 映射
User user = DB.Jdbc.select("SELECT * FROM user WHERE id = ?", 1)
.queryOne(User.class);

// 列表映射
List<User> users = DB.Jdbc.select("SELECT * FROM user WHERE status = ?", 1)
.queryList(User.class);

复杂类型映射

@Data
public class UserDTO {
private Long id;
private String name;

// 嵌套对象(假设查询结果有 dept_id, dept_name)
private Department dept;

// JSON 字段自动解析
private List<String> tags;

// Map 类型
private Map<String, Object> extra;
}

// 查询时自动映射
UserDTO dto = DB.Jdbc.select("""
SELECT u.*, d.id as dept_id, d.name as dept_name
FROM user u
LEFT JOIN department d ON u.dept_id = d.id
WHERE u.id = ?
""", 1).queryOne(UserDTO.class);

6.2 Map 映射

ResultMap

DLZ-DB 的查询结果默认返回 ResultMap,它继承自 JSONMap,具有强大的取值能力。

// 查询返回 ResultMap
ResultMap result = DB.Table.select("user")
.eq("id", 1)
.queryOne();

// 基础取值
Long id = result.getLong("id");
String name = result.getStr("name");
Integer age = result.getInt("age", 0); // 带默认值
Date createTime = result.getDate("create_time");

列表查询

// 返回 ResultMap 列表
List<ResultMap> list = DB.Table.select("user")
.eq("status", 1)
.queryList();

// 遍历处理
for (ResultMap item : list) {
String name = item.getStr("name");
Integer age = item.getInt("age");
}

// 转换为 Bean 列表
List<User> users = list.stream()
.map(m -> m.toBean(User.class))
.collect(Collectors.toList());

不需要定义实体类的场景

// 报表统计:不需要为每个报表定义 DTO
ResultMap stats = DB.Jdbc.select("""
SELECT
COUNT(*) as total,
SUM(amount) as total_amount,
AVG(amount) as avg_amount,
MAX(amount) as max_amount
FROM orders
WHERE create_time >= ?
""", startDate).queryOne();

long total = stats.getLong("total");
BigDecimal totalAmount = stats.getBigDecimal("total_amount");
BigDecimal avgAmount = stats.getBigDecimal("avg_amount");

6.3 ResultMap 深度取值

核心能力

ResultMap 继承自 JSONMap,支持:

  1. 深度路径取值a.b.c[0].d
  2. 负数索引list[-1] 获取最后一个元素
  3. 智能类型转换:自动转换为目标类型
  4. 空值安全:中间任意节点为空不会报错
  5. 嵌套 JSON 字符串解析:自动解析

深度取值

ResultMap result = DB.Jdbc.select("SELECT * FROM user WHERE id = 1").queryOne();

// 假设返回的数据结构:
// {
// "id": 1,
// "name": "张三",
// "profile": {
// "address": {
// "city": "北京",
// "district": "朝阳区"
// },
// "tags": ["开发者", "架构师", "DBA"]
// },
// "orders": [
// {"id": 101, "amount": 100},
// {"id": 102, "amount": 200}
// ]
// }

// 深度取值
String city = result.getStr("profile.address.city"); // "北京"
String district = result.getStr("profile.address.district"); // "朝阳区"

// 数组取值
String firstTag = result.getStr("profile.tags[0]"); // "开发者"
String lastTag = result.getStr("profile.tags[-1]"); // "DBA"(负数索引)

// 嵌套对象取值
Long orderId = result.getLong("orders[0].id"); // 101
BigDecimal amount = result.getBigDecimal("orders[-1].amount"); // 200

默认值

// 路径不存在时返回默认值,不会报空指针
String city = result.getStr("profile.address.city", "未知");
Integer score = result.getInt("score", 0);
List<String> tags = result.getList("profile.tags", String.class, Collections.emptyList());

类型转换

// 自动类型转换
Integer age = result.getInt("age"); // 数字 → Integer
Long id = result.getLong("id"); // 数字 → Long
Double score = result.getDouble("score"); // 数字 → Double
BigDecimal amount = result.getBigDecimal("amount");
Boolean active = result.getBoolean("active"); // 支持 true/false, 1/0, "true"/"false"
Date createTime = result.getDate("create_time");

// 获取嵌套对象
ResultMap profile = result.getMap("profile");
ResultMap address = result.getMap("profile.address");

// 获取列表
List<String> tags = result.getList("profile.tags", String.class);
List<Order> orders = result.getList("orders", Order.class);

// 转换为 Bean
User user = result.toBean(User.class);
Address addr = result.getBean("profile.address", Address.class);

嵌套 JSON 字符串

// 假设 config 字段存储的是 JSON 字符串:
// {"theme": "dark", "language": "zh"}

// 传统方式需要先解析字符串
String configStr = result.getStr("config");
JSONObject config = JSON.parseObject(configStr);
String theme = config.getString("theme");

// ResultMap 自动解析
String theme = result.getStr("config.theme"); // 直接获取
ResultMap config = result.getMap("config"); // 获取为 Map

与 ValUtil 配合

ResultMap result = ...;

// 获取原始值
Object raw = result.get("some_field");

// 使用 ValUtil 转换
Integer num = ValUtil.toInt(raw, 0);
List<String> list = ValUtil.toList(raw, String.class);
User user = ValUtil.toObj(raw, User.class);