Kotlin搭配Exposed ORM和KGraphql初始化Schema报泛型不支持错误
问题原因
你遇到的报错是因为Exposed ORM的实体类(继承IntEntity)自带多个ORM内部使用的非业务属性,其中包含泛型类型kotlin.collections.Map<org.jetbrains.exposed.sql.Expression<*>, kotlin.Int>。KGraphQL默认会扫描注册类的所有属性,而GraphQL规范不支持泛型Map类型,因此触发异常。
解决方案
方案1:显式指定GraphQL类型暴露的属性
修改Schema定义代码,在注册ExposedFeed和ExposedEntry类型时,仅声明你需要对外暴露的业务字段,排除Exposed内部属性即可:
fun SchemaBuilder.RSSFeedschema() { query("RSSFeeds") { resolver { -> transaction { ExposedFeed.all() } } } type<ExposedFeed> { // 仅显式注册需要暴露的业务字段 property("id") { it.id.value } property(ExposedFeed::description) property(ExposedFeed::docs) property(ExposedFeed::feedType) property(ExposedFeed::link) property(ExposedFeed::author) property(ExposedFeed::authors) property(ExposedFeed::categories) property(ExposedFeed::language) property(ExposedFeed::title) property(ExposedFeed::uri) property(ExposedFeed::webMaster) property(ExposedFeed::timestamp) } type<ExposedEntry> { property("id") { it.id.value } property(ExposedEntry::title) property(ExposedEntry::author) property(ExposedEntry::description) property(ExposedEntry::categories) property(ExposedEntry::contents) property(ExposedEntry::comments) property(ExposedEntry::uri) property(ExposedEntry::publishedDate) property(ExposedEntry::updatedDate) // 如果需要关联返回Feed信息也可以加上 property("feed") { it.exposedFeed } } }
方案2:新增DTO层做数据转换(更推荐)
不要直接把Exposed ORM实体暴露给GraphQL层,定义普通Kotlin数据类作为传输对象,返回前做一层转换,从根源上避免ORM内部属性泄露:
- 定义DTO类和转换方法
// Feed DTO data class RSSFeedDTO( val id: Int, val description: String, val docs: String?, val feedType: String?, val link: String?, val author: String?, val authors: String?, val categories: String?, val language: String?, val title: String?, val uri: String?, val webMaster: String?, val timestamp: String? ) // Entry DTO data class RSSEntryDTO( val id: Int, val title: String, val author: String?, val description: String?, val categories: String?, val contents: String?, val comments: String?, val uri: String?, val publishedDate: String?, val updatedDate: String? ) // 扩展方法实现实体转DTO fun ExposedFeed.toDTO() = RSSFeedDTO( id = id.value, description = description, docs = docs, feedType = feedType, link = link, author = author, authors = authors, categories = categories, language = language, title = title, uri = uri, webMaster = webMaster, timestamp = timestamp )
- 修改Schema定义和resolver
fun SchemaBuilder.RSSFeedschema() { query("RSSFeeds") { resolver { -> transaction { ExposedFeed.all().map { it.toDTO() } } } } // 直接注册DTO类型,不会有多余内部属性 type<RSSFeedDTO>() type<RSSEntryDTO>() }
内容的提问来源于stack exchange,提问作者SomethingsGottaGive
相关产品推荐
相关产品推荐

