babyfish-ct / jimmer

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

计算属性通过DTO View抓取时出现 `UnloadedException` 异常 #648

Closed aboutZZ closed 2 months ago

aboutZZ commented 2 months ago

版本

Jimmer 0.8.158

问题复现

系统使用 RBAC 经典鉴权体系:

角色实体定义了一个计算属性authorities,方便获取角色的权限。 用户实体定义了一个计算属性,以获取用户的授权权限(该属性依赖于角色实体计算属性authorities)。

@Entity
interface SystemRole : AbstractEntity {

    @ManyToMany(orderedProps = [OrderedProp("sort")])
    @JoinTable(name = "sys_role_permission", joinColumnName = "role_id", inverseJoinColumnName = "permission_id")
    val permissions: List<SystemPermission>

    /**
     * 权限菜单
     */
    @IdView("permissions")
    val permissionIds: List<Long>

    /**
     * 计算角色权限集合
     */
    @Formula(dependencies = ["permissions.authority"])
    val authorities: Set<String>
        get() = permissions.mapNotNull { it.authority }.filter { it.isNotEmpty() }.toSet()

}

@Entity
interface SystemUser : AbstractEntity, DepartmentAware {

    @ManyToMany(orderedProps = [OrderedProp("sort")])
    @JoinTable(name = "sys_user_role", joinColumnName = "user_id", inverseJoinColumnName = "role_id")
    val roles: List<SystemRole>

    /**
     * 计算用户权限集合
     */
    @Formula(dependencies = ["roles.authorities", "roles.permissions.authority"])
    val authorities: Set<String>
        get() = roles.flatMap { it.authorities }.toSet()
}

接下来进行查询(Fetcher与DTO View定义的形状一致)

// 1. 使用Fetcher查询正常
sql.createQuery(SystemUser::class) {
    where(table.username eq username)
    select(table.fetchBy {
        allScalarFields()
        department()
        roles {
            allScalarFields()
        }
        authorities()
    })
}.fetchOneOrNull()

// 2. 使用DTO语言的View查询(抓取形状与上述一致)

// DTO 定义
SystemUserPermissionView {
    #allScalars
    id(department)
    roles {
        #allScalars(this)
    }
    authorities
}
// DTO View 查询异常: UnloadedException
sql.createQuery(SystemUser::class) {
    where(table.username eq username)
    select(table.fetch(SystemUserPermissionView::class))
}.fetchOneOrNull()

使用DTO语言的View查询报错:

org.babyfish.jimmer.UnloadedException: The property "io.elva.frameworks.data.domain.system.SystemRole.permissions" is unloaded