MyBatis-Flex 开发指南
1. 概述
MyBatis-Flex 通过为常见的数据访问任务提供更便捷的编程模型,扩展了 MyBatis 生态系统。
在本教程中,我们将构建一个小型 Spring Boot 4 应用程序,以探索 MyBatis-Flex 的核心工作流程,从项目设置到数据访问代码。具体来说,我们将定义一个简单的实体类和映射器(Mapper),执行基本的 CRUD 操作,使用 QueryWrapper 创建过滤查询,并对结果进行分页。
本文中的示例需要 Java 17 或更高版本。
2. 设置最小化 Spring Boot 项目
Spring Boot 简化了 MyBatis-Flex 的设置过程,使我们能够更专注于映射器和查询 API。
2.1. 添加依赖
尽管 MyBatis-Flex 消除了通常与直接 JDBC 访问相关的许多样板代码,并且我们可以将其作为 JPA 或 Hibernate 的替代方案,但它仍然依赖于 Spring JDBC 基础架构来进行数据源配置和管理。
MyBatis-Flex 支持超过 40 种不同的数据库类型,包括 MySQL、PostgreSQL、Oracle、SQL Server 和 SQLite。在本例中,我们使用 H2 作为内存数据库,因为它有助于创建快速、隔离且可重复的测试。
为此,我们将 MyBatis-Flex、Spring JDBC、H2 和 Spring Boot Test Starter 依赖项添加到 Spring Boot 4 的 pom.xml 中:
在继续之前,建议查看 Maven Repository 以获取更新的版本。
2.2. 配置数据源 (H2)
接下来,我们在 src/main/resources/application.yml 中配置数据源:
URL jdbc:h2:mem:mybatisflex 在应用程序上下文中创建了一个内存数据库。用户名为 sa 且密码为空是 H2 的默认设置。
spring.sql.init 部分指示 Spring Boot 使用 SQL 脚本初始化数据源。在本例中,它从 src/main/resources/db/schema-h2.sql 加载架构,并从 src/main/resources/db/data-h2.sql 加载示例数据。
2.3. 启用 Mapper 扫描
最后,在主 Spring Boot 应用程序类中启用 Mapper 扫描。在 MyBatis-Flex 中,Mapper 是将 Java 代码与实体数据库操作连接起来的组件:
启用 Mapper 扫描后,Spring 可以检测到 AccountMapper,为其创建一个 Bean,并允许我们将其注入到测试中。
3. 创建实体和 Mapper
项目配置完成后,让我们定义领域模型和 MyBatis-Flex 用于持久化操作的 Mapper。
3.1. 使用注解定义简单实体
首先,我们可以从映射到 tb_account 表的简单 Account 实体开始。MyBatis-Flex 使用注解将类与表关联,并自定义字段如何映射到数据库列:
这里,@Table 将类绑定到 tb_account 表,而 @Id 标记主键并将其配置为自动生成的值。值得注意的是,对于 Java 字段名与列名不直接匹配的情况(如 userName 和 createdAt),我们也使用了 @Column。其余字段遵循默认命名约定,因此无需额外注解。
3.2. 创建继承 BaseMapper<T> 的 Mapper 接口
接下来,定义 Account 的 Mapper 接口。在 MyBatis-Flex 中,Mapper 是暴露实体数据访问操作的组件:
通过继承 BaseMapper<Account>,AccountMapper 继承了一套丰富的内置操作,用于插入、更新、删除和查询。这保持了接口的简洁性,同时提供了我们在本文示例中所需的一切。
3.3. 初始化架构和测试数据
在编写针对数据库的任何 Java 代码之前,先添加一个小型的架构和几行示例数据。我们将两个脚本放在 src/main/resources/db 下,以便 Spring Boot 在启动时自动加载它们。
首先,创建 schema-h2.sql:
接下来是 data-h2.sql:
示例数据为集成测试提供了可预测的数据集。由于行在年龄、状态和创建时间上有所不同,我们可以在多个示例中重复使用它们,而无需在每个测试中添加额外的设置代码。
4. 基本 CRUD 操作
现在我们有了基础模型,让我们看看在实际应用程序中最先执行的数据操作:插入、读取、更新和删除。
首先,将 Mapper 直接注入测试类:
此时,我们可以开始添加测试了。
4.1. 插入并根据 ID 检索
尝试一个简单的持久化流程:
这里,我们创建了一个 Account,通过 Mapper 插入它,然后根据生成的 id 检索它,以验证记录是否正确存储。
4.2. 更新现有记录
更新现有记录同样简单。首先加载一个实体,修改其中一个字段,最后将其传回 Mapper 以持久化更改:
再次读取同一行数据,确认新值已按预期写入数据库。
4.3. 删除记录
此测试确认 deleteById() 删除了记录,并且后续的查询会返回 null:
但在实际操作中,许多应用程序会避免对业务数据进行物理删除,而是倾向于软删除策略,以便记录仍可用于审计或恢复。
5. 使用 QueryWrapper 编写查询
到目前为止,我们已经使用了 Mapper 进行直接的 CRUD 操作。为了实现更具表现力的读取,MyBatis-Flex 提供了 QueryWrapper,这是一个用于在 Java 代码中构建 SQL 条件的流畅 API。
5.1. 多条件查询与排序
首先从结合过滤和排序的查询开始。这是应用程序代码中的常见模式,即使涉及多个条件,QueryWrapper 也能保持良好的可读性:
在本例中,我们仅选择了成年且状态为“ACTIVE”的账户,并按年龄降序排列。结果断言明确了排序逻辑,帮助我们验证生成的查询是否符合预期。
5.2. 动态查询
在许多实际搜索场景中,某些过滤器是可选的。与其创建多个查询变体,不如逐步构建 QueryWrapper,仅在存在相应参数时添加每个条件:
这种方法在不牺牲清晰度的前提下,保持了查询逻辑的灵活性。
5.3. 执行分页查询
分页是将大型结果集拆分为较小的块(或页面)的常用方法,而不是一次性加载所有匹配行。MyBatis-Flex 通过 Mapper 直接支持分页,因此我们可以请求特定的页面和页面大小,而无需引入单独的分页抽象:
上面我们对过滤后的结果进行了分页,并验证了返回的记录和页面元数据。这一点非常有用,因为分页不仅仅是限制行数。通常,我们还需要匹配记录的总数和页面总数来构建周围的应用程序逻辑。
6. 结论
在本文中,我们构建了一个使用 MyBatis-Flex 的小型 Spring Boot 4 项目,并以此演示了核心的持久化工作流程。我们配置了 H2 数据源,定义了实体和 Mapper,并使用 JUnit 5 集成测试验证了设置。
此外,我们看到了 MyBatis-Flex 如何支持简单和更具表现力的数据访问模式。具体来说,我们使用了 BaseMapper 的内置 CRUD 操作,通过 QueryWrapper 创建了过滤查询,并运行了分页查询,同时检查了返回的记录和页面元数据。
一如既往,本文的完整代码可在 GitHub 上找到。