SQLDelight 2.0.2是否需为每个Int类型列手动添加EntityAdapter?
在SQLDelight 2.x版本中,当你在SQL查询或表定义里使用AS Int进行显式类型转换时,生成的实体适配器不会自动绑定默认的IntColumnAdapter,这确实会导致大量重复代码。不过你可以通过以下几种方式避免手动重复配置:
1. 优先使用原生SQL类型,避免多余的AS Int
如果你的列本身在SQL中就是INTEGER类型,完全不需要在查询里额外加AS Int——SQLDelight会自动将原生SQL整数类型映射为Kotlin的Int,并自动生成对应的适配器逻辑,不需要手动传入IntColumnAdapter。
比如将:
SELECT some_column AS Int FROM first_entity
改为:
SELECT some_column FROM first_entity
只要some_column的SQL类型是INTEGER,生成的FirstEntity类中对应的属性会自动是Int类型,适配器也会自动处理。
2. 注册全局默认列适配器
你可以在创建数据库驱动时,注册全局的Int类型适配器,这样所有需要适配Int类型的列都会自动使用这个适配器,无需在每个实体适配器中手动指定:
fun getDatabase( driverFactory: DriverFactory, dbName: String, encryptionKey: String ): Database { val driver = driverFactory.createDriver(dbName, encryptionKey).apply { // 注册全局Int类型适配器 registerColumnAdapter(Int::class, IntColumnAdapter) } // 这里无需再为每个Entity.Adapter传入适配器参数 return Database(driver = driver) }
3. 在Gradle配置中指定类型映射
如果必须保留AS Int的显式转换,可以通过SQLDelight的Gradle配置,指定SQL类型到Kotlin类型的映射,并绑定默认适配器,让生成代码时自动包含适配器参数:
在build.gradle.kts中添加:
sqldelight { databases { create("Database") { packageName.set("com.your.package") typeMapping { // 将SQL中的"Int"类型映射到Kotlin Int,并指定默认适配器 addMapping("Int", Int::class, "IntColumnAdapter") } } } }
配置后重新生成代码,所有涉及AS Int的列对应的适配器参数会自动填充,无需手动编写。
4. 封装适配器创建逻辑减少样板
如果以上方法都不适用,可以用Kotlin扩展函数封装重复的适配器创建逻辑:
// 扩展函数,自动填充所有Int类型的适配器参数 fun FirstEntity.Companion.defaultAdapter() = FirstEntity.Adapter( aAdapter = IntColumnAdapter, bAdapter = IntColumnAdapter, cAdapter = IntColumnAdapter, // ... 其他需要的适配器参数 )
然后在创建数据库时直接使用:
return Database( driver = driver, FirstEntityAdapter = FirstEntity.defaultAdapter(), // ... 其他实体适配器 )
为什么会出现这个问题?
SQLDelight 2.x对类型映射的逻辑做了更严格的区分:当你使用AS Int显式转换类型时,框架无法确定这个转换是从何种原始类型而来(比如可能是String转Int),因此不会自动绑定默认的IntColumnAdapter,需要开发者明确指定。但对于原生SQL整数类型的列,框架会自动完成类型映射和适配器绑定。
内容的提问来源于stack exchange,提问作者Paul Frank Allan

