当前使用版本(必填,否则不予处理)

3.5.3.1

该问题是如何引起的?(确定最新版也有问题再提!!!)

源码中KtQueryWrapper继承的Query接口传的泛型是KProperty<*>,代码如下:

open class KtQueryWrapper<T : Any> : AbstractKtWrapper<T, KtQueryWrapper<T>>, Query<KtQueryWrapper<T>, T, KProperty<*>> {
  ...
}

会导致在使用的时候,没有泛型进行约束,比如下面这段代码也可以编译通过

KtUpdateWrapper(User()).eq(OtherUser::otherName, "sss") 

我目前尝试改动泛型为KMutableProperty1是可以做到约束的,比如:

open class KtQueryWrapper<T : Any> : AbstractKtWrapper<T, KtQueryWrapper<T>>, Query<KtQueryWrapper<T>, T, KMutableProperty1<T, *>> {
  ...
}

重现步骤(如果有就写完整)


import com.baomidou.mybatisplus.annotation.TableField
import com.baomidou.mybatisplus.annotation.TableName
import com.baomidou.mybatisplus.core.MybatisConfiguration
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper
import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper
import org.apache.ibatis.builder.MapperBuilderAssistant

fun main() {
    TableInfoHelper.initTableInfo(MapperBuilderAssistant(MybatisConfiguration(), ""), User::class.java)
    TableInfoHelper.initTableInfo(MapperBuilderAssistant(MybatisConfiguration(), ""), OtherUser::class.java)
    println(KtQueryWrapper(User()).select(User::name).eq(User::name, "sss").sqlSegment)
    println(KtQueryWrapper(User()).select(OtherUser::otherName).eq(OtherUser::otherName, "sss").sqlSegment)
}

@TableName("sys_user")
class User {

    var id: Int? = null

    @TableField("username")
    var name: String? = null

    var roleId: Int? = null
}

@TableName("other_user")
class OtherUser {

    var id: Int? = null

    var otherName: String? = null

    var roleId: Int? = null
}

报错信息

Comment From: miemieYaho

https://github.com/baomidou/mybatis-plus/commit/276ea9895dc56d6d50ce81c7e3af769a9252f0d3

Comment From: c332030

这样我没法使用基类了

Comment From: c332030

MyBatis-Plus KtQueryWrapper和KtUpdateWrapper泛型限制问题

Comment From: c332030

这种怎么处理,列名对上不就行了吗

Comment From: c332030

变量也不能用 val 修饰了,有些字段直接用 sql 修改,查回来后不需要改,用 val 很正常吧

Comment From: c332030

@miemieYaho 辛苦帮忙看看

Comment From: c332030

interface ICService<T : Any> : IService<T> {

    fun update(whereChain: (KtUpdateChainWrapper<T>) -> KtUpdateChainWrapper<T>): Boolean {

        val wrapper = whereChain.invoke(ktUpdate())

        val now = Instant.now()

        if (IUpdater::class.java.isAssignableFrom(entityClass)) {
            wrapper.set(IUpdater::updater, getUserId())
            wrapper.set(IUpdateTime::updateTime, now)
        } else if (IUpdateTime::class.java.isAssignableFrom(entityClass)) {
            wrapper.set(IUpdateTime::updateTime, now)
        }

        return wrapper.update()
    }

}

Comment From: c332030

interface IUpdateTime {

    @get:ApiModelProperty("更新时间")
    var updateTime: Instant?

}

interface IUpdater : IUpdateTime {

    @get:ApiModelProperty("更新人")
    @get:JsonSerialize(using = ToStringSerializer::class)
    var updater: Long?

}

data class User(

    var id: Long? = null,

    override var updater: Long? = null,
    override var updateTime: Instant? = null,

): IUpdater

Comment From: c332030

这样也会报错

interface ICUpdaterService<T: IUpdater> : ICService<T> {

    override fun update(whereChain: (KtUpdateChainWrapper<T>) -> KtUpdateChainWrapper<T>): Boolean {
        return super.update{
            it.set(IUpdater::updater, getUserId())
        }
    }

}

MyBatis-Plus KtQueryWrapper和KtUpdateWrapper泛型限制问题

Comment From: c332030

这样用不了的 MyBatis-Plus KtQueryWrapper和KtUpdateWrapper泛型限制问题

Comment From: c332030

这种重复性的更新操作,难道每次都写一遍吗

Comment From: initchen

这样也会报错

```kotlin interface ICUpdaterService : ICService {

override fun update(whereChain: (KtUpdateChainWrapper<T>) -> KtUpdateChainWrapper<T>): Boolean {
    return super.update{
        it.set(IUpdater::updater, getUserId())
    }
}

} ```

试试强转呢it.set(IUpdater::updater as KMutableProperty1, getUserId())

Comment From: initchen

变量也不能用 val 修饰了,有些字段直接用 sql 修改,查回来后不需要改,用 val 很正常吧

数据库实体类用final修复的字段,查询后也能赋值吗,有这个场景的话,源码的泛型由KMutableProperty1改为KProperty1是同时支持var和val

Comment From: c332030

这样也会报错 ```kotlin interface ICUpdaterService : ICService {

override fun update(whereChain: (KtUpdateChainWrapper<T>) -> KtUpdateChainWrapper<T>): Boolean {
    return super.update{
        it.set(IUpdater::updater, getUserId())
    }
}

} ```

试试强转呢it.set(IUpdater::updater as KMutableProperty1, getUserId())

你好,这样不报错但是有警告,关掉警告会导致其他有意义的警告显示不了吧,虽然这里没有喽 有的警告虽然不影响编译,但是可能导致线上报错 MyBatis-Plus KtQueryWrapper和KtUpdateWrapper泛型限制问题

Comment From: initchen

这样也会报错 ```kotlin interface ICUpdaterService : ICService {

override fun update(whereChain: (KtUpdateChainWrapper<T>) -> KtUpdateChainWrapper<T>): Boolean {
    return super.update{
        it.set(IUpdater::updater, getUserId())
    }
}

} ```

试试强转呢it.set(IUpdater::updater as KMutableProperty1, getUserId())

你好,这样不报错但是有警告,关掉警告会导致其他有意义的警告显示不了吧,虽然这里没有喽 有的警告虽然不影响编译,但是可能导致线上报错

关闭警告的范围有代码行、方法、类、整个文件,你压制代码行或者方法应该就可以了,比如下面是关闭单行的

@Suppress("UNCHECKED_CAST")
wrapper.set(IUpdater::updater as KMutableProperty1<T, *>, 1)
@Suppress("UNCHECKED_CAST")
wrapper.set(IUpdater::updateTime as KMutableProperty1<T, *>, now)

Comment From: c332030

这样也会报错 ```kotlin interface ICUpdaterService : ICService {

override fun update(whereChain: (KtUpdateChainWrapper<T>) -> KtUpdateChainWrapper<T>): Boolean {
    return super.update{
        it.set(IUpdater::updater, getUserId())
    }
}

} ```

试试强转呢it.set(IUpdater::updater as KMutableProperty1, getUserId())

你好,这样不报错但是有警告,关掉警告会导致其他有意义的警告显示不了吧,虽然这里没有喽 有的警告虽然不影响编译,但是可能导致线上报错

关闭警告的范围有代码行、方法、类、整个文件,你压制代码行或者方法应该就可以了,比如下面是关闭单行的

@Suppress("UNCHECKED_CAST") wrapper.set(IUpdater::updater as KMutableProperty1<T, *>, 1) @Suppress("UNCHECKED_CAST") wrapper.set(IUpdater::updateTime as KMutableProperty1<T, *>, now)

这样是可以,但是我是想能不关闭警告还是不要关闭警告,我先降级吧

KMutableProperty1改为KProperty1 我觉得还是有必要的,更新一两个字段用 set 更新,就不用考虑赋值了,直接传实体过去更新还会忽略 null

Comment From: c332030

KProperty1 这样限定可以传父类可以吗,我第一次 fork 各种问题编译不了

Comment From: initchen

KProperty1 这样限定可以传父类可以吗,我第一次 fork 各种问题编译不了

确实可以传父类了

Comment From: c332030

KProperty1 这样限定可以传父类可以吗,我第一次 fork 各种问题编译不了

确实可以传父类了

好的,谢谢