【原创】Kotlin使用Lambda形式的QueryWrapper进行查询,解决SpringBoot中Kotlin无法使用LambdaQueryWrapper执行查询的问题

前言

众所周知,Kotlin无法使用LambdaQueryWrapper进行查询,会无法找到相关Lambda表达式的方法,导致报错,这就导致Kotlin因为这么一个小问题变得不香了,当然这个问题也很好解决。

报错如下:

【原创】Kotlin使用Lambda形式的QueryWrapper进行查询,解决SpringBoot中Kotlin无法使用LambdaQueryWrapper执行查询的问题_第1张图片

代码如下:

        val lambdaQueryWrapper = LambdaQueryWrapper()
        lambdaQueryWrapper.like(ExampleEntity::name,  qo.name)
        lambdaQueryWrapper.gt(ExampleEntity::number, qo.number)
        val selectList1 = exampleMapper.selectList(lambdaQueryWrapper)
        logInfo("selectList1 is ${selectList1.toJson()}")

网上已经有很多说明为什么会报错的文章了,我这就不再赘述了

解决方案1:手撸一个查询类

不就是通过方法名获取字段名吗,我自己写一个转换类不就行了!反射走起!

直接上代码:

package com.itdct.server.system.dict

import cn.hutool.core.util.StrUtil
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
import com.itdct.server.common.util.log.logInfo
import com.itdct.server.system.dict.entity.SysDictEntity
import kotlin.reflect.KFunction

/**
 * @author DCT
 * @date 2023/10/23 18:05:39
 * @version 1.0
 * @description
 */

class KQueryWrapper : QueryWrapper() {

    fun eq(function: KFunction, value: Any?, ignoreIfNull: Boolean = true): KQueryWrapper {
        value?.also {
            eq(getTableFieldName(function), value)
        } ?: also {
            if (!ignoreIfNull) {
                eq(getTableFieldName(function), value)
            }
        }
        return this
    }

    fun like(function: KFunction, value: Any?, ignoreIfNull: Boolean = true): KQueryWrapper {
        value?.also {
            like(getTableFieldName(function), value)
        } ?: also {
            if (!ignoreIfNull) {
                like(getTableFieldName(function), value)
            }
        }
        return this
    }

    fun notLike(function: KFunction, value: Any?, ignoreIfNull: Boolean = true): KQueryWrapper {
        value?.also {
            notLike(getTableFieldName(function), value)
        } ?: also {
            if (!ignoreIfNull) {
                notLike(getTableFieldName(function), value)
            }
        }
        return this
    }

    fun ne(function: KFunction, value: Any?, ignoreIfNull: Boolean = true): KQueryWrapper {
        value?.also {
            ne(getTableFieldName(function), value)
        } ?: also {
            if (!ignoreIfNull) {
                ne(getTableFieldName(function), value)
            }
        }
        return this
    }

    fun gt(function: KFunction, value: Any?, ignoreIfNull: Boolean = true): KQueryWrapper {
        value?.also {
            gt(getTableFieldName(function), value)
        } ?: also {
            if (!ignoreIfNull) {
                gt(getTableFieldName(function), value)
            }
        }
        return this
    }

    fun lt(function: KFunction, value: Any?, ignoreIfNull: Boolean = true): KQueryWrapper {
        value?.also {
            lt(getTableFieldName(function), value)
        } ?: also {
            if (!ignoreIfNull) {
                lt(getTableFieldName(function), value)
            }
        }
        return this
    }

    fun between(function: KFunction, left: Any?, right: Any?): KQueryWrapper {
        if (left == null || right == null) {
            return this
        }
        between(getTableFieldName(function), left, right)
        return this
    }

    fun notBetween(function: KFunction, left: Any?, right: Any?): KQueryWrapper {
        if (left == null || right == null) {
            return this
        }
        notBetween(getTableFieldName(function), left, right)
        return this
    }

    fun isNull(function: KFunction): KQueryWrapper {
        isNull(getTableFieldName(function))
        return this
    }

    fun isNotNull(function: KFunction): KQueryWrapper {
        isNotNull(getTableFieldName(function))
        return this
    }

    fun getTableFieldName(function: KFunction): String {
        val functionName = function.name
        var prefixLength = 0
        if (functionName.startsWith("get") || functionName.startsWith("set")) {
            prefixLength = 3
        } else if (functionName.startsWith("is")) {
            prefixLength = 2
        }
        var tableFieldName = ""

        if (prefixLength != 0) {
            var fieldName = functionName.substring(prefixLength)
            fieldName = fieldName.substring(0, 1).lowercase() + fieldName.substring(1)
//            val declaredField = clazz.getDeclaredField(fieldName)
//            val tableField = declaredField.getAnnotation(TableField::class.java)
//            if (tableField != null) {
//                // INFO: DCT: 2023/10/24 存在tableField注解,则使用tableField注解中的内容
//                tableFieldName = tableField.value
//            } else {
            tableFieldName = StrUtil.toUnderlineCase(fieldName)
//            }
            logInfo("tableFieldName is $tableFieldName")
            return tableFieldName
        } else {
            return tableFieldName
        }
    }

}

fun main() {
    val kQueryWrapper = KQueryWrapper()
    kQueryWrapper.eq(SysDictEntity::getRemark, 15).eq(SysDictEntity::getParentId, 12)
}

入参为KFunction也就是Kotlin的方法,就通过方法名去解析出数据库的字段名就行了,本来还想加TableField注解去转换,后来想想反射比较消耗性能,索性不加更好,要用TableField就直接写字段名吧。

这个方法还有一个好处,如果为空,能不加上这个查询,省得再手动判断了。当然继承自QueryWrapper,它自带的方法也是可以用的。

使用例子如下:

        val kQueryWrapper = KQueryWrapper()
        kQueryWrapper.like(ExampleEntity::getName, qo.name)
            .gt(ExampleEntity::getNumber, qo.number)
        val selectList = exampleMapper.selectList(kQueryWrapper)

解决方案2:MP自带

当我撸完上面这段代码后,发现MybatisPlus居然自带一个KtQueryWrapper,这把我气得,原来MP自己就有,我的时间都浪费了,不过这个自带的有个问题,它的入参是KProperty,也就是成员变量,关键是这个类必须是KotlinBean,不能是JavaBean,这就带来了一些局限,如果这个类是别人Java写好的实体类,这玩意就用不了了,而我的解决方案1没有这个顾虑,因为传入的是方法。

查询写法如下:

        val ktQueryWrapper = KtQueryWrapper(ExampleEntity::class.java)
        ktQueryWrapper.like(ExampleEntity::name, qo.name)
            .gt(ExampleEntity::number, qo.number)
        val selectList2 = exampleMapper.selectList(ktQueryWrapper)

好处是起来更省事,不用再加get了,直接使用成员变量名即可,看看源码实在是太优雅了,不得不说MP作者还是强啊。

【原创】Kotlin使用Lambda形式的QueryWrapper进行查询,解决SpringBoot中Kotlin无法使用LambdaQueryWrapper执行查询的问题_第2张图片

你可能感兴趣的:(Kotlin,java,springboot,kotlin,springboot,mybatis)