Kotlin 版 MyBatis-Plus 查询优雅解决方案

Kotlin 版 MyBatis-Plus 查询优雅解决方案

从 Java 切换到 Kotlin 之后,总觉得 MyBatis-Plus 的查询写法还是啰嗦:要么用 KtQueryWrapper 写一长串 User::getName,要么在动态搜索表单里写一堆 if-else 判空,视觉噪音还是大

于是我写了一个扩展库 ------ mybatis-plus-kt ,利用 KProperty1 属性引用,让你用类型安全、接近自然语言的风格写查询,彻底告别字符串和重复判空。

kotlin 复制代码
// 就这样,读起来像说话一样自然
User::name eq "btown"
User::age ge 18
User::role `in` listOf("admin", "dev")

✨ 核心亮点

  • 类型安全User::name 是编译期检查的,再也不会把字段名写错
  • 类自然语言User::age between (18 to 60) 读作"年龄在 18 到 60 之间"
  • 零配置:Spring Boot 自动配置,引入依赖即用
  • 安全模式ktWhereSafe { } 里 null / 空集合自动跳过,零 if-else
  • 无侵入 :复用 QueryWrapper,直接 .selectList() 就能执行

🚀 5 分钟快速上手

1. 引入依赖

Gradle

kotlin 复制代码
implementation("io.github.btown021:mybatis-plus-kt-spring-boot-starter:1.0.1")

Maven

xml 复制代码
<dependency>
    <groupId>io.github.btown021</groupId>
    <artifactId>mybatis-plus-kt-spring-boot-starter</artifactId>
    <version>1.0.1</version>
</dependency>

2. 定义实体与 Service

kotlin 复制代码
@TableName("sys_user")
data class User(
    var name: String = "",
    var age: Int = 0,
    var status: Int = 0,
    var role: String = ""
) : BaseAttr()

interface IUserService : IService<User>
class UserServiceImpl : ServiceImpl<UserMapper, User>(), IUserService

3. 查询就是这么简单

kotlin 复制代码
@Service
class UserBizService(private val userService: IUserService) {

    fun search(name: String?, status: Int?, roleList: List<String>?): List<User> {
        return userService.createQueryWrapper<User>()
        	// 安全模式:自动跳过 null,空集合生成永假条件,between 单端 null 自动降级
            .ktWhereSafe {
                User::name like name             // null 自动跳过
                User::status eq status           // null 自动跳过
                User::role in null				// null 自动跳过
                User::role in enmptyList()       // 转换为生成永假条件 (无匹配)
                User::age between (null to 60)   // 降级为 age <= 60
                User::age between (18 to null)   // 降级为 age >= 18
                User::age between (null to null) // 自动跳过
            }
        	// 普通模式 原生MP行为 不进行null的跳过 降级等
        	.ktWhere {
                User::name like name
                User::status eq status 
            }
            .ktOrder { User::id.orderByDesc }
            .selectList()
    }
}

空集合的智能处理:in 操作遇到空集合时,不能简单跳过(否则会查出全部数据),安全模式会自动生成 1<>1,保证结果为空,更符合业务直觉。notIn 空集合则直接跳过。

不用写一行 if (name != null) { ... },安全模式帮你把所有空判断都处理好了。

🤯 减少 if-else 样板代码 (安全模式)

原生写法:

kotlin 复制代码
val wrapper = QueryWrapper<User>()
if (name != null) wrapper.lambda().like(User::getName, name)
if (status != null) wrapper.lambda().eq(User::getStatus, status)
if (ageMin != null) wrapper.lambda().ge(User::getAge, ageMin)
if (ageMax != null) wrapper.lambda().le(User::getAge, ageMax)
if (!roleList.isNullOrEmpty()) wrapper.lambda().`in`(User::getRole, roleList)

mybatis-plus-kt 写法:

kotlin 复制代码
userService.createQueryWrapper()
    .ktWhereSafe {
        User::name like name
        User::status eq status
        User::age between (ageMin to ageMax)
        User::role in roleList
    }
    .selectList()

代码量直接减半,可读性肉眼可见地提升。

🧩 强大的逻辑组合

支持 and / or / anyOf 等逻辑,复杂条件也写得优雅:

kotlin 复制代码
ktWhere {
    User::status eq 1
    and {
        User::role eq "admin"
        or {
            User::level ge 5
            User::vip eq true
        }
    }
}
// 生成 SQL: WHERE status = 1 AND (role = 'admin' OR level >= 5 OR vip = TRUE)

// anyOf:对同一字段的多候选值 OR 匹配
anyOf(listOf("a", "b", "c")) {
    User::name like it
}
// SQL: WHERE (name LIKE '%a%' OR name LIKE '%b%' OR name LIKE '%c%')

排序、指定返回列也都支持,且保持同样的自然语法:

kotlin 复制代码
.ktOrder { User::status.orderByAsc; User::id.orderByDesc }
.ktSelect(User::id, User::name)

⚙️ 自定义列名映射

默认从 @TableField 读取映射,你也可以实现 ColumnNameProvider 来覆盖:

kotlin 复制代码
override fun resolveFieldColumnMap(): Map<String, String> = mapOf(
    "name" to "user_name"
)

甚至支持运行时动态列名(分表、多租户场景),只需将 isDynamic() 设为 true 即可。

📦 环境

  • Kotlin 2.2+ / JDK 17+
  • MyBatis-Plus 3.5.3+
  • Spring Boot 3.0+

🎯 总结

mybatis-plus-kt 在不改变 MyBatis-Plus 原有使用习惯的前提下,用 Kotlin 特性让查询代码更安全、更简洁,写起来就像说话一样自然。特别适合动态查询多、表单搜索频繁的后台系统。如果你也在用 Kotlin 写 Spring Boot,强烈推荐试一下。

👉 GitHub: github.com/btown021/my... 👉 Gitee: gitee.com/btown/mybat...

(顺手点个 Star 支持一下呗 ⭐)

相关推荐
bytebitx16 小时前
MacOS 编译腾讯 Mars XLog 及使用(已16KB对齐)
kotlin·mac·apk
alexhilton2 天前
让架构边界变成可执行的测试
android·kotlin·android jetpack
数据治理自习室2 天前
AI 应用评测体系(GraphRAG)
android·大数据·人工智能·kotlin
名剑走天下3 天前
Android 面试题大全
android·kotlin
chjif3 天前
Android 设备管控开发实战:自定义 Launcher 如何只显示指定 App?
android·kotlin
非凡ghost3 天前
用 Kotlin 和 Jetpack Compose 重写的安卓视频播放器,原生体验有多流畅?
android·java·kotlin·音视频·软件需求
名剑走天下3 天前
android 面试题
kotlin
蜡台4 天前
Jetpack Compose 稳定性、重组优化(Stable / @NonRestartableComposable)
android·kotlin·compose·jepack
JMchen1234 天前
Jetpack 内核实战(十):实战(下)——编辑页、全局设置与内存泄漏排查
kotlin·内存泄漏·android 实战·datastore 设置·jetpack 项目优化·编辑页开发
雨白5 天前
Kotlin 泛型基础:“万能魔法盒”的诞生
kotlin