MyBatis-Flex数据库操作实战指南:从基础到高级应用

9 次阅读 0 点赞 0 评论原创后端开发

MyBatis-Flex轻量级ORM框架实战指南,聚焦Db、QueryWrapper、DbChain核心类,助开发者灵活控制SQL。涵盖单表CRUD、连表查询、分页、事务、批量操作等,附使用场景与最佳实践。无论新手还是有经验用户,皆可高效掌握数据库操作技巧。

#MyBatis-Flex #Java #ORM框架 #数据库操作 #CRUD #SQL查询 #后端开发
MyBatis-Flex数据库操作实战指南:从基础到高级应用

MyBatis-Flex 数据库操作实战指南:从基础到高级应用

作为一款轻量级的ORM框架,MyBatis-Flex提供了简洁而强大的数据库操作能力。本文将系统介绍基于DbQueryWrapperDbChain三个核心类的使用方法,特别适合那些需要灵活控制SQL的开发者。无论你是MyBatis-Flex新手还是有经验的用户,这份指南都能帮助你更高效地进行数据库操作。

目录

1. 单表基础操作(CRUD)

1.1 简单插入/更新/删除 - 推荐使用 Db

Db类提供了简洁的静态方法,适合执行简单的数据库操作。

插入操作

java 复制代码
// 基本插入
Row user = new Row();
user.set("name", "张三");
user.set("age", 25);
user.set("email", "zhangsan@example.com");
int result = Db.insert("user", user); // 返回影响行数

// 使用SQL插入 - 适合字段较少的场景
int result = Db.insertBySql("INSERT INTO user(name, age) VALUES(?, ?)", "李四", 30);

// 批量插入 - 高效处理多条记录
List<Row> users = Arrays.asList(user1, user2, user3);
int[] results = Db.insertBatch("user", users); // 返回每条记录的影响行数

更新操作

java 复制代码
// 根据ID更新
Row updateData = new Row();
updateData.set("name", "李四");
updateData.set("age", 26);
int result = Db.updateById("user", updateData.setId("id", 1));

// 使用SQL更新 - 适合复杂条件更新
int result = Db.updateBySql("UPDATE user SET status = ? WHERE age > ?", 1, 18);

// 根据条件更新
Map<String, Object> whereCondition = Map.of("status", 0);
int result = Db.updateByMap("user", updateData, whereCondition);

删除操作

java 复制代码
// 根据ID删除
int result = Db.deleteById("user", "id", 1);

// 根据条件删除
Map<String, Object> condition = Map.of("status", 0);
int result = Db.deleteByMap("user", condition);

// 使用SQL删除 - 适合复杂条件删除
int result = Db.deleteBySql("DELETE FROM user WHERE created_at < ?", lastMonth);

1.2 链式操作 - 推荐使用 DbChain

DbChain提供了流畅的链式API,使代码更具可读性和可维护性。

链式插入

java 复制代码
boolean success = DbChain.table("user")
    .set("name", "王五")
    .set("age", 30)
    .set("email", "wangwu@example.com")
    .save(); // 插入并返回操作是否成功

链式更新

java 复制代码
boolean updated = DbChain.table("user")
    .set("status", 1)
    .set("updated_at", new Date())
    .where("id = ?", 1)
    .update(); // 更新并返回操作是否成功

链式删除

java 复制代码
boolean deleted = DbChain.table("user")
    .where("status = ? AND created_at < ?", 0, lastMonth)
    .remove(); // 删除并返回操作是否成功

2. 单表查询操作

2.1 简单查询 - 推荐使用 Db

Db类的查询方法适合快速获取数据,支持多种查询方式。

基础查询

java 复制代码
// 根据ID查询单条记录
Row user = Db.selectOneById("user", "id", 1);

// 根据条件查询单条记录
Map<String, Object> condition = Map.of("email", "test@example.com");
Row user = Db.selectOneByMap("user", condition);

// 查询满足条件的列表
List<Row> users = Db.selectListByMap("user", condition);

// 查询表中所有记录
List<Row> allUsers = Db.selectAll("user");

SQL查询

java 复制代码
// 直接SQL查询 - 适合复杂条件查询
String sql = "SELECT * FROM user WHERE status = ? AND age >= ?";
List<Row> users = Db.selectListBySql(sql, 1, 18);

// 查询单个值 - 适合聚合函数查询
Object maxAge = Db.selectObject("SELECT MAX(age) FROM user WHERE status = ?", 1);

// 统计查询 - 快速获取记录数
long count = Db.selectCount("SELECT COUNT(*) FROM user WHERE status = ?", 1);

2.2 链式查询 - 推荐使用 DbChain

DbChain的链式查询API使查询条件的构建更加直观和灵活。

基础链式查询

java 复制代码
// 单条查询
Row user = DbChain.table("user")
    .where("email = ?", "test@example.com")
    .one(); // 获取单条记录

// 可选查询(避免空指针异常)
Optional<Row> userOpt = DbChain.table("user")
    .where("id = ?", 1)
    .oneOpt(); // 获取Optional包装的记录

// 列表查询
List<Row> activeUsers = DbChain.table("user")
    .where("status = ? AND age >= ?", 1, 18)
    .orderBy("created_at DESC")
    .limit(10) // 限制返回记录数
    .list(); // 获取记录列表

统计和检查

java 复制代码
// 统计记录数
long count = DbChain.table("user")
    .where("status = ?", 1)
    .count();

// 检查记录是否存在
boolean exists = DbChain.table("user")
    .where("email = ?", "test@example.com")
    .exists();

// 查询单个值
Object maxSalary = DbChain.table("user")
    .select("MAX(salary)") // 指定查询字段
    .where("dept_id = ?", 1)
    .obj(); // 获取单个值

3. 连表查询

3.1 简单连表 - 推荐直接写SQL

对于简单的连表查询,直接编写SQL通常是最直观和高效的方式。

java 复制代码
// 两表连接查询
String sql = """
    SELECT u.*, r.role_name 
    FROM user u 
    LEFT JOIN role r ON u.role_id = r.id 
    WHERE u.status = ? AND r.status = ?
    """;
List<Row> result = Db.selectListBySql(sql, 1, 1);

// 多表连接查询
String complexSql = """
    SELECT 
        u.name, 
        d.dept_name, 
        COUNT(p.id) as project_count
    FROM user u
    LEFT JOIN department d ON u.dept_id = d.id
    LEFT JOIN user_project up ON u.id = up.user_id
    LEFT JOIN project p ON up.project_id = p.id
    WHERE u.status = ? AND d.status = ?
    GROUP BY u.id, d.id
    HAVING COUNT(p.id) > ?
    ORDER BY project_count DESC
    """;
List<Row> complexResult = Db.selectListBySql(complexSql, 1, 1, 0);

3.2 动态连表 - 使用 QueryWrapper

当连表条件需要动态构建时,QueryWrapper提供了灵活的API来构建查询。

java 复制代码
// 构建动态连表查询
QueryWrapper query = QueryWrapper.create()
    .select("u.*", "r.role_name", "d.dept_name")
    .from("user u")
    .leftJoin("role r").on("u.role_id = r.id")
    .leftJoin("department d").on("u.dept_id = d.id")
    .where("u.status = ?", 1);

// 动态添加条件
if (roleId != null) {
    query.and("u.role_id = ?", roleId);
}
if (deptId != null) {
    query.and("u.dept_id = ?", deptId);
}
if (StringUtil.hasText(keyword)) {
    query.and("u.name LIKE ?", "%" + keyword + "%");
}

query.orderBy("u.created_at DESC");
List<Row> users = Db.selectListByQuery(query); // 执行查询

3.3 表别名设置 - 使用 QueryWrapper

在复杂查询中,合理使用表别名可以使SQL更清晰易读。MyBatis-Flex提供了多种设置表别名的方式:

为主表设置别名

java 复制代码
// 方法1:使用as()方法为主表设置别名
QueryWrapper query = QueryWrapper.create()
    .select("u.*")
    .from("user")
    .as("u")  // 为user表设置别名u
    .where("u.status = ?", 1);

// 生成SQL: SELECT u.* FROM user u WHERE u.status = ?

// 方法2:在from()方法中直接设置别名
QueryWrapper query = QueryWrapper.create()
    .select("u.*")
    .from(new QueryTable("user").as("u"))
    .where("u.status = ?", 1);

为连接表设置别名

java 复制代码
QueryWrapper query = QueryWrapper.create()
    .select("u.*", "r.role_name")
    .from("user u")  // 主表直接设置别名
    .leftJoin("role r")  // 连接表直接设置别名
    .on("u.role_id = r.id")
    .where("u.status = ?", 1);

// 或者使用QueryTable对象
QueryWrapper query = QueryWrapper.create()
    .select("u.*", "r.role_name")
    .from(new QueryTable("user").as("u"))  // 主表别名
    .leftJoin(new QueryTable("role").as("r"))  // 连接表别名
    .on("u.role_id = r.id");

子查询别名

java 复制代码
// 子查询作为表使用时设置别名
QueryWrapper subQuery = QueryWrapper.create()
    .select("dept_id", "COUNT(*) as user_count")
    .from("user")
    .where("status = ?", 1)
    .groupBy("dept_id");

QueryWrapper mainQuery = QueryWrapper.create()
    .select("d.dept_name", "uc.user_count")
    .from("department d")
    .leftJoin(subQuery).as("uc").on("d.id = uc.dept_id");  // 子查询别名

4. 复杂查询

4.1 子查询

子查询是处理复杂数据关系的强大工具,MyBatis-Flex支持各种类型的子查询。

IN子查询

java 复制代码
String subQuerySql = """
    SELECT u.* FROM user u 
    WHERE u.dept_id IN (
        SELECT d.id FROM department d 
        WHERE d.region = ? AND d.status = ?
    ) 
    AND u.salary > (
        SELECT AVG(salary) FROM user WHERE dept_id = u.dept_id
    )
    """;
List<Row> result = Db.selectListBySql(subQuerySql, "华东", 1);

EXISTS子查询

java 复制代码
String existsSql = """
    SELECT u.* FROM user u 
    WHERE EXISTS (
        SELECT 1 FROM user_role ur 
        WHERE ur.user_id = u.id AND ur.role_id = ?
    )
    """;
List<Row> usersWithRole = Db.selectListBySql(existsSql, 1);

4.2 窗口函数查询

窗口函数是现代数据库提供的高级特性,可以进行复杂的数据分析。

java 复制代码
// 排名查询
String rankSql = """
    SELECT 
        name, 
        salary, 
        dept_id,
        ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC) as rank_in_dept,
        RANK() OVER (ORDER BY salary DESC) as overall_rank
    FROM user 
    WHERE status = ?
    """;
List<Row> rankedUsers = Db.selectListBySql(rankSql, 1);

// 累计统计
String cumulativeSql = """
    SELECT 
        DATE(created_at) as date,
        COUNT(*) as daily_count,
        SUM(COUNT(*)) OVER (ORDER BY DATE(created_at)) as cumulative_count
    FROM user 
    WHERE created_at >= ?
    GROUP BY DATE(created_at)
    ORDER BY date
    """;
List<Row> stats = Db.selectListBySql(cumulativeSql, startDate);

5. 分页查询

MyBatis-Flex提供了多种分页方式,可根据查询复杂度选择合适的方案。

5.1 简单分页 - 使用 Db.paginate

对于单表查询或简单连表查询,Db.paginate方法可以快速实现分页。

java 复制代码
// 构建查询条件
QueryWrapper query = QueryWrapper.create()
    .select("*")
    .from("user")
    .where("status = ?", 1)
    .orderBy("created_at DESC");

// 执行分页查询 - 参数:表名、页码、每页大小、查询条件
Page<Row> page = Db.paginate("user", 1, 20, query);

// 访问分页结果
System.out.println("总记录数: " + page.getTotalRow());
System.out.println("总页数: " + page.getTotalPage());
System.out.println("当前页数据: " + page.getRecords());

5.2 链式分页 - 使用 DbChain

DbChain提供了更流畅的分页API,适合单表分页查询。

java 复制代码
Page<Row> page = new Page<>(1, 20); // 创建分页对象,设置页码和每页大小
Page<Row> result = DbChain.table("user")
    .where("status = ? AND age >= ?", 1, 18)
    .orderBy("salary DESC", "created_at DESC")
    .page(page); // 执行分页查询

// 已知总数的分页(性能优化)
Page<Row> pageWithTotal = new Page<>(2, 20, 1000L); // 指定总数避免重复统计
Page<Row> result = DbChain.table("user")
    .where("status = ?", 1)
    .page(pageWithTotal);

5.3 复杂连表分页

对于复杂查询,推荐使用手动分页方式,完全控制SQL执行过程。

java 复制代码
// 1. 先查询总数
String countSql = """
    SELECT COUNT(*) FROM user u 
    LEFT JOIN department d ON u.dept_id = d.id 
    WHERE u.status = ? AND d.region = ?
    """;
long total = Db.selectCount(countSql, 1, "华东");

// 2. 再查询分页数据
String dataSql = """
    SELECT u.*, d.dept_name 
    FROM user u 
    LEFT JOIN department d ON u.dept_id = d.id 
    WHERE u.status = ? AND d.region = ?
    ORDER BY u.salary DESC 
    LIMIT ? OFFSET ?
    """;

int pageNum = 1, pageSize = 20;
int offset = (pageNum - 1) * pageSize;
List<Row> data = Db.selectListBySql(dataSql, 1, "华东", pageSize, offset);

// 3. 手动构建分页对象
Page<Row> page = new Page<>(pageNum, pageSize, total);
page.setRecords(data);

5.4 分页方式选择建议

分页方式 适用场景 优点 缺点
Db.paginate 单表查询、简单连表查询 代码简洁,自动处理计数和分页 对复杂查询支持有限
DbChain.page 单表链式查询 API流畅,代码可读性好 不适合复杂连表查询
手动分页 复杂连表查询、子查询、特殊SQL 完全控制SQL,灵活性最高 代码量较大

选择建议:优先使用Db.paginateDbChain.page处理简单分页,对于复杂查询场景则采用手动分页方式。

6. 事务操作

事务管理是确保数据一致性的关键,MyBatis-Flex提供了简洁的事务API。

6.1 简单事务

java 复制代码
// 布尔返回值事务
boolean success = Db.tx(() -> {
    // 插入用户
    Row user = new Row();
    user.set("name", "张三");
    user.set("email", "zhangsan@example.com");
    Db.insert("user", user);
    
    // 插入用户角色关系
    Row userRole = new Row();
    userRole.set("user_id", user.get("id"));
    userRole.set("role_id", 1);
    Db.insert("user_role",
最后更新:2025-08-20 12:52:36

评论 (0)

发表评论

blog.comments.form.loading
0/500
加载评论中...

相关文章

TypeScript SDK:MCP服务端客户端开发利器,高效处理LLM上下文

TypeScript SDK:MCP服务端客户端开发利器,高效处理LLM上下文。作为Model Context Protocol官方实现工具,该SDK简化MCP服务端与客户端开发流程,助力开发者轻松管理LLM上下文,提升AI应用构建效率,是2025年处理MCP协议与LLM交互的实用技术方案。

2025-09-28

better-sqlite3:Node.js中最快SQLite3库,提升数据库操作效率与性能

better-sqlite3:2025年Node.js环境中高性能SQLite解决方案,作为Node.js SQLite的性能标杆,采用同步API设计却实现超越异步方案的并发性能。这款经近十年优化的SQLite3库,能有效提升数据库操作效率,助力开发者优化Node.js数据库性能,是轻量级高性能JavaScript数据库的理想选择。

2025-09-20