众所周知,Kotlin无法使用LambdaQueryWrapper进行查询,会无法找到相关Lambda表达式的方法,导致报错,这就导致Kotlin因为这么一个小问题变得不香了,当然这个问题也很好解决。
报错如下:
代码如下:
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()}")
网上已经有很多说明为什么会报错的文章了,我这就不再赘述了
不就是通过方法名获取字段名吗,我自己写一个转换类不就行了!反射走起!
直接上代码:
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)
当我撸完上面这段代码后,发现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作者还是强啊。