You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中ModelMapper映射后AWPainting参数值丢失问题

问题根源

你遇到的awPainting值被覆盖的问题,核心原因是**AWPainting是Kotlin的object单例类**,而AWThought中默认将painting属性指向这个唯一的单例实例。

当ModelMapper执行thought.map(AWThought::class.java)时,它会自动初始化AWThought的所有属性,包括painting。由于painting是单例对象,ModelMapper会直接修改这个单例内部的字段(比如id),将其重置为类定义时的默认值0——而你传入的awPainting参数本质上就是这个单例,所以映射后它的id自然变成了0,表现为background00000。

验证逻辑

你可以在映射前后打印awPainting === AWPainting,结果一定是true,说明两者是同一个对象。映射时ModelMapper修改了单例的状态,导致参数值被篡改。

解决方案

方案1:将AWPainting从单例改为普通类(推荐)

单例不适合作为数据载体(尤其是需要多个不同实例的场景),把object改成class,每次创建独立实例:

// 去掉object,改成class
class AWPainting: Serializable {
    var id: Int = 0
    var author: String = ""
    var authorEmail: String = ""
    var url: String = ""
    var filename: String = ""
    var active: Int = 0
    var thoughtId: Int = 0

    // 原init方法可调整为构造函数或依赖注入方式初始化
    constructor() {}
    constructor(id: Int, author: String, /* 其他参数 */) {
        this.id = id
        this.author = author
        // 赋值其他属性
    }

    // 其余方法保持不变,注意静态相关逻辑需调整
    override fun toString(): String {
        return "background" + String.format(Locale.getDefault(), "%04d", id)
    }
}

同时修改AWThought中painting的默认值:

// 从单例改为创建新实例,或按需初始化
var painting: AWPainting = AWPainting()

这样每个AWPainting实例都是独立的,ModelMapper映射时只会修改当前AWThought对应的实例,不会影响传入的参数。

方案2:配置ModelMapper忽略painting属性的映射

如果必须保留单例,可以让ModelMapper在映射AWThought时跳过painting属性,避免修改单例状态:

// 初始化ModelMapper时添加自定义映射规则
modelMapper.addMappings(object : PropertyMap<AWThoughtDTO, AWThought>() {
    override fun configure() {
        skip(destination.painting) // 跳过painting属性的自动映射
    }
})

这样映射时ModelMapper不会修改painting单例,你后续手动赋值mapThought.painting = awPainting就能保持参数的原有值。

方案3:映射前后保存/恢复单例状态(临时 workaround)

如果暂时无法修改单例结构,可在映射前保存AWPainting的当前状态,映射后恢复:

fun getRandomThought(
    context: Context?,
    idLanguage: Int,
    awPainting: AWPainting,
    trackId: Int
): AWThought {
    // 保存单例当前状态
    val savedId = AWPainting.id
    val savedAuthor = AWPainting.author
    val savedFilename = AWPainting.filename
    // 保存其他需要保留的字段
    
    val mapAlreadyReadThoughts = mapAll(alreadyReadThoughts, AWThoughtDTO::class.java)
    val thought = thoughtService.getRandomThought(idLanguage, mapAlreadyReadThoughts)
    val mapThought = thought.map(AWThought::class.java)
    
    // 恢复单例状态
    AWPainting.id = savedId
    AWPainting.author = savedAuthor
    AWPainting.filename = savedFilename
    // 恢复其他字段
    
    mapThought.painting = awPainting
    mapThought.trackId = trackId
    setThoughtTrackIds(mapThought, trackId)
    alreadyReadThoughts.add(mapThought)
    saveAlreadyReadThoughtsList(alreadyReadThoughts, context)
    return mapThought
}

这种方式只是临时解决,不推荐长期使用,因为单例的状态共享会带来其他潜在问题。

内容的提问来源于stack exchange,提问作者Diego Perez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 10:36:24