我正在尝试创建一个特性来将数据从hive表加载到类型化的数据集中。这是代码:
import org.apache.spark.sql.{Dataset, Row, SparkSession}
trait PartitionedHiveTableLoader[T] {
def context: String
def table: String
def returnEntity: Row => T
def load(sparkSession: SparkSession, token: String): Dataset[T] = {
import sparkSession.implicits._
sparkSession.sql(s"SELECT * from $context.$table where d = $token").
map(returnEntity(_))
}
def load(sparkSession: SparkSession, lowBound: String, upperBound: String, includeLow: Boolean = true, includeUpper: Boolean = true): Dataset[T] = {
import sparkSession.implicits._
sparkSession.sql(s"SELECT * " +
s"from $context.$table " +
s"where d >${if(includeLow)"=" else ""} $lowBound " +
s"and d<${if(includeUpper)"=" else ""} $upperBound").
map(returnEntity(_))
}
}
然后这个特征与Object一起使用如下:
import org.apache.spark.sql.Row
object FreeUsersRightsLoader extends {} with PartitionedHiveTableLoader[FreeUsersRightsEntity] {
def context: String = "analytics"
def table: String = "free_users_rights"
def returnEntity: Row => FreeUsersRightsEntity = x => FreeUsersRightsDataset(x)
}
但是当我用mvn包编译它时,我有以下错误:
错误:无法找到存储在数据集中的类型的编码器。导入spark.implicits.支持原始类型(Int,String等)和产品类型(case类)。将来版本中将添加对序列化其他类型的支持。
但我在每种方法中都引入了spark.implicits ...... 有人知道问题是什么吗?
答案 0 :(得分:1)
类型Encoder
的隐式T
必须在编译时可用于您正在使用的方法。
导入import sparkSession.implicits._
时,实际上为许多已知常见类型(例如String,Long,Arrays,case classes等)导入了一堆内置编码器,但是 - T
未知和未绑定,因此它可能是任何,而且任何类都没有内置编码器 - 因此导入无用。
要解决此问题 - 您应该将隐式编码器参数添加到方法签名中:
def load(sparkSession: SparkSession, token: String)(implicit enc: Encoder[T]): Dataset[T] = {
sparkSession.sql(s"SELECT * from $context.$table where d = $token").
map(returnEntity(_))
}
def load(sparkSession: SparkSession,
lowBound: String,
upperBound: String,
includeLow: Boolean = true,
includeUpper: Boolean = true)(implicit enc: Encoder[T]): Dataset[T] = {
sparkSession.sql(s"SELECT * " +
s"from $context.$table " +
s"where d >${if(includeLow)"=" else ""} $lowBound " +
s"and d<${if(includeUpper)"=" else ""} $upperBound").
map(returnEntity(_))
}
然后,只要这些方法被称为,你就需要内置的隐式 - 其中类型T被称为FreeUsersRightsEntity
(我假设它是这些中的一个-in类,例如包含基元和集合的案例类):
import spark.implicits._
FreeUsersRightsLoader.load(spark, "token")