Ktor中通用BaseService的getOne()方法实现报错问题
通用BaseService实现方案(解决Prisma Schema类型不匹配问题)
核心问题分析
你遇到的类型不匹配错误,本质是构建查询条件时没有正确返回Op<Boolean>类型的表达式,而是误写了无返回值的代码块(返回Unit),导致和select方法所需参数类型不兼容。
正确的BaseService抽象类实现
基于所有表使用String类型UUID作为主键的前提,我们可以通过泛型+抽象方法实现通用CRUD基础方法:
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.transactions.transaction abstract class BaseService<T : Table, E>(private val table: T) { // 抽象属性:子类指定主键列(统一为String类型UUID) protected abstract val primaryKeyColumn: Column<String> // 抽象方法:子类实现数据表行到实体类的转换 protected abstract fun rowToEntity(row: ResultRow): E // 获取全量数据 fun getAll(): List<E> = transaction { table.selectAll().map(::rowToEntity) } // 根据UUID主键获取单条数据 fun getOne(id: String): E? = transaction { table.select { primaryKeyColumn eq id } .singleOrNull() ?.let(::rowToEntity) } }
子类实现示例(以Category为例)
假设Prisma生成的CategorySchema和对应的实体类如下,子类只需实现主键列指定和行转实体逻辑:
// Prisma生成的Category表Schema object CategorySchema : Table() { val id = varchar("id", 36) val name = varchar("name", 100) // 其他业务字段... override val primaryKey = PrimaryKey(id) } // 业务实体类 data class Category( val id: String, val name: String // 对应其他字段... ) // Category业务服务类 class CategoryService : BaseService<CategorySchema, Category>(CategorySchema) { override val primaryKeyColumn = CategorySchema.id override fun rowToEntity(row: ResultRow): Category { return Category( id = row[CategorySchema.id], name = row[CategorySchema.name] // 其他字段映射... ) } }
错误写法的问题说明
- 第一种错误(Required: Op Found: Unit):你在
select的条件块中没有返回eq表达式,比如写成{ table.id eq id }但漏了返回值(Kotlin中代码块最后一行是返回值,若没写则返回Unit)。正确写法是直接传递primaryKeyColumn eq id这个Op类型的表达式。 - 第二种错误(Required: List<Expression<*>> Found: () → Unit):错误地将无返回值的代码块作为参数传给select,而select需要的是查询条件表达式列表,需确保传递的是
Op<Boolean>类型的条件。
内容的提问来源于stack exchange,提问作者ImEmo
相关产品推荐
相关产品推荐

