babyfish-ct / jimmer

A revolutionary ORM framework for both java and kotlin.
Apache License 2.0
882 stars 91 forks source link

[Help] DTO语言的View并没有执行ID以外的JsonConverter #758

Closed ThatCoders closed 3 weeks ago

ThatCoders commented 3 weeks ago

问题

先阐述一下问题,下面贴代码, 开启了Redis缓存。也不了解Jimmer来问问。

  1. test请求。第一次请求打印SQL,接口返回的json里pass未脱敏但是查看Redis发现Redis缓存成功而且缓存的是脱敏后的,所以第二次请求返回接口是脱敏的(走缓存)。
  2. login请求。每次都是返回未脱敏的,因为账号名查找用户手动开启缓存的原因?

返回给控制层时候SysUserLoginView(entity)就不会触发ID外的Converter,直接抛eneity出去每次都能脱敏。

简化代码

entity

@Entity
@Table(name = "sys_user")
interface SysUser : RestrictEntity {

    @Id
    @GeneratedValue(generatorType = SnowGenerator::class)
    @JsonConverter(LongToStringConverter::class)
    val id: Long

    @Key
    val account: String

    @JsonConverter(StringMaskConverter::class) // DTO 不触发ID外的Converter
    val pass: String
}

repository

@Repository
interface SysUserRepository : KRepository<SysUser, Long> {
    @Cacheable(cacheNames = ["Base::SysUser"])
    fun findByAccount(account: String): SysUser?
}

dto文件

export cn.thatcoder.base.entity.SysUser

input SysUserLoginInput {
    account
    pass
}
SysUserLoginView {
    #allScalars
}

service

@Service
class SysUserService(private val sysUserRepository: SysUserRepository) : ISysUserService {
    override fun login(input: SysUserLoginInput): SysUserLoginView? {
        val loginUser = this.findUser(input.account)
        return if (loginUser != null && PassUtil.matches(input.pass, loginUser.pass)) {
            SysUserLoginView(loginUser)
        } else null
    }
    override fun findUser(id: Long): SysUser? {
        return sysUserRepository.findById(id).getOrNull()
    }
    override fun findUser(account: String): SysUser? {
        return sysUserRepository.findByAccount(account)
    }
}

controller

@RestController
@RequestMapping("/sys/user")
open class SysUserController(private var sysUserService: SysUserService) {
    @PostMapping("/login")
    open fun login(@RequestBody @Valid input: SysUserLoginInput): Response {
        return Response.autoWarn(sysUserService.login(input))
    }
    @PostMapping("/test")
    open fun test(): Response {
        return Response.autoWarn(
            sysUserService.findUser(1853191227709583360L)?.let { SysUserLoginView(it) }
            // sysUserService.findUser(1853191227709583360L)  // 这个不SysUserLoginView转化就没问题
        )
    }
}
ThatCoders commented 3 weeks ago

还是打扰一下,我知道只要让view是可变或再转一遍实体,比如.toImmutable()就可以达到DTO定义的形状。但是为什么直接抛dto出去不能经过converter呢?

@RestController
@RequestMapping("/sys/user")
open class SysUserController(private var sysUserService: SysUserService) {
    @PostMapping("/login")
    open fun login(@RequestBody @Valid input: SysUserLoginInput): Response {
        return Response.autoWarn(sysUserService.login(input)?.toImmutable())
    }
    @PostMapping("/test")
    open fun test(): Response {
        return Response.autoWarn(
            sysUserService.findUser(1853191227709583360L)?.let { SysUserLoginView(it).toImmutable() }
        )
    }
}

我知道这个代码是OK的,一切都能正常脱敏与缓存。

babyfish-ct commented 3 weeks ago

这几天在加一个大功能,等几天哈

ThatCoders commented 3 weeks ago

这几天在加一个大功能,等几天哈

没问题,涛哥先忙

babyfish-ct commented 3 weeks ago

Try 0.9.11

ThatCoders commented 2 weeks ago

Try 0.9.11

感谢Commit,完美解决!

babyfish-ct commented 2 weeks ago

感谢@Enaium 的PR

ThatCoders commented 2 weeks ago

已 follow @Enaium 🎉