使用Kotlin Dataframe读取SQLite时Integer转Boolean抛出类型转换异常
解决Kotlin Dataframe读取SQLite布尔列时的ClassCastException问题
问题背景
SQLite无原生Boolean类型,以1/0存储布尔值。使用Kotlin Dataframe读取包含这类列的表时,抛出类型转换异常:
java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.Boolean (java.lang.Integer and java.lang.Boolean are in module java.base of loader 'bootstrap') at Cell In[0], line 13
执行脚本:
USE { dependencies("org.xerial:sqlite-jdbc:3.47.1.0") } %use kandy %use dataframe val connection = DriverManager.getConnection("jdbc:sqlite:../data/data.db") val repositories = DataFrame.readSqlTable(connection, "Repositories") println(repositories.columnNames()) println(repositories.columnTypes()) println(repositories[3].is_disabled)
输出显示列类型被推断为kotlin.Boolean,但实际JDBC返回的是Integer值,导致强制转换失败:
[id, name, size, project_id, default_branch, is_disabled] [kotlin.String, kotlin.String, kotlin.Long, kotlin.String?, kotlin.String?, kotlin.Boolean] java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.Boolean (java.lang.Integer and java.lang.Boolean are in module java.base of loader 'bootstrap') at Cell In[0], line 13
Exposed可正常解析,说明不是数据本身问题,而是Dataframe默认读取逻辑未适配SQLite的布尔存储规则。
原因分析
- SQLite JDBC驱动将存储的1/0以
Integer类型返回,但Kotlin Dataframe在自动推断列类型时,误将对应列识别为Boolean,直接执行强制类型转换引发异常。 - Exposed内部针对SQLite做了适配,自动将Integer类型的1/0转换为Boolean值,而Dataframe默认SQL读取逻辑没有处理这种特定场景。
解决方案
1. 读取后手动转换列类型
读取数据后,将Integer类型的列转换为Boolean(支持可空列):
// 非空布尔列 val repositories = DataFrame.readSqlTable(connection, "Repositories") .convert<Int>("is_disabled") { it == 1 } // 可空布尔列 val repositories = DataFrame.readSqlTable(connection, "Repositories") .convert<Int?>("is_disabled") { it?.let { it == 1 } }
2. 配置JDBC连接强制返回Boolean类型
通过连接属性配置SQLite驱动,让其将1/0以Boolean类型返回:
import java.util.Properties val props = Properties() // 告诉SQLite驱动将对应列按Boolean类型处理 props.setProperty("sqlite.jdbc.booleanType", "BOOLEAN") val connection = DriverManager.getConnection("jdbc:sqlite:../data/data.db", props) val repositories = DataFrame.readSqlTable(connection, "Repositories")
注:该配置需要xerial sqlite-jdbc 3.30.0及以上版本支持。
3. 显式指定列类型读取
使用readSqlTable的重载方法,手动指定列的目标类型,避免自动推断错误:
// 非空布尔列 val repositories = DataFrame.readSqlTable( connection, "Repositories", columnTypes = mapOf("is_disabled" to Boolean::class) ) // 可空布尔列 val repositories = DataFrame.readSqlTable( connection, "Repositories", columnTypes = mapOf("is_disabled" to Boolean?::class) )
内容的提问来源于stack exchange,提问作者jlengrand
相关产品推荐
相关产品推荐

