读取 BigInt
类型的 MySQL 列(例如下面的 BIGINT(21) UNSIGNED
)时,Spark 无法强制转换 java.math.BigDecimal
到以下代码段中的 String
:
val driver = "com.mysql.jdbc.Driver"
val server = ...
val infoSchema = "INFORMATION_SCHEMA"
val port = 3306
val user = ...
val pw = ...
val dbUrl = s"jdbc:mysql://$server:$port/$infoSchema"
val dbProperties = new java.util.Properties()
dbProperties.setProperty("driver", driver)
dbProperties.setProperty("user", user)
dbProperties.setProperty("password", pw)
val schema = ...
val table = ...
val cols = sqlContext.read.jdbc(dbUrl, "COLUMNS", dbProperties)
.filter(col("TABLE_SCHEMA") === schema && col("TABLE_NAME") === table)
.map(_.getValuesMap[String](Seq("ORDINAL_POSITION", "COLUMN_NAME")))
.collect()
.toList
cols.map(e => e("COLUMN_NAME"))
cols.map(e => e("ORDINAL_POSITION")) // java.math.BigDecimal cannot be cast to java.lang.String
但是,当我执行以下操作时,没有问题:
val num = new java.math.BigDecimal(1)
num.toString
这是一个错误还是我遗漏了什么?
最佳答案
Row.getValuesMap[T]
不用于类型转换。相反,它明确声明值的类型为 T
(内部它只是一个 get
后跟 asInstanceOf[T]
)和 BigDecimal
显然不是 String
。
你可以:
- 添加隐式转换。
- 使用
_.getValuesMap[Any]
。 在映射之前使用 SQL 转换。
withColumn("ORDINAL_POSITION", $"ORDINAL_POSITION".cast(StringType))
但说实话,所有这些选项都相当丑陋,直接提取值更有意义:
sqlContext.read.jdbc(...).filter(...)
.select("ORDINAL_POSITION", "COLUMN_NAME")
.rdd
.map { case Row(i: java.math.BigDecimal, c: String) => (i, c) }
关于mysql - Spark 1.4.1 : Issue when reading MySQL BigInt columns,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39080789/