带有转义字段名的scala case类在spark catalyst代码生成过程中引发错误

xdyibdwo  于 2021-06-24  发布在  Hive
关注(0)|答案(2)|浏览(361)

我有一个带有转义字段名的case类,例如:

case class Buyer(`52_week`: String, `26_week`: String,... other fields)

然后我创建这个类的一个示例并传递给spark dataframe,如下所示:

val expected = spark.createDataFrame(sc.parallelize(List(buyer1, buyer2)))

当我试图保存它时:

expected.write.mode(SaveMode.Append).format("hive").partitionBy("load_date").saveAsTable(tableName)

我得到以下例外:

Caused by: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 476, Column 15: failed to compile: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 476, Column 15: Expression "funcResult15 = value65" is not a type

其中476行是:

/* 475 */           Object funcResult15 = null;
/* 476 */           funcResult15 = value65.52_week();

所以我需要告诉catalyst codegen逃离这些字段。
有没有办法解决这个问题,或者至少有解决办法?
我使用的是apachespark2.2.0。

unguejic

unguejic1#

我建议你换个Angular case class 构造器在旧对象的基础上构建对象时:

case class BuyerRenamed(week_52: String, week_26: String,... other fields)
object BuyerRenamed {
  def apply(buyer: Buyer): BuyerRenamed = {
    BuyerRenamed(buyer.`52_week`, buyer.`26_week`, ...)
  }
}

然后将新的case类与dataframes一起使用,这将解决catalyst的问题,因为字段的名称如下 value65.week_52() ,这是方法的适当命名。
也许您需要添加隐式转换以使代码更干净。
从长远来看,我建议您重构现有代码以摆脱这种命名,它可能会导致各种突发错误,特别是当您以某种方式与自动代码生成联系在一起时。

qeeaahzv

qeeaahzv2#

我所做的是将buyer类转换为tuple,并明确指出要使用哪些列名。
换句话说,我通过选择不同的路径来绕过代码生成。
代码段如下所示:

val expected = spark.createDataFrame(sc.parallelize(List(buyer1, buyer2).map(b => Brand.unapply(b).get))).toDF(extractFieldNames[Buyer]:_*)

其中,字段名是:

def extractFieldNames[T<:Product](implicit m: Manifest[T]): Array[String] =
    m.erasure.getDeclaredFields.map(_.getName)

相关问题