UDF不使用外部变量[Java spark]
我正在尝试执行以下代码 我将数据集作为输入,使用Groovyshell对其执行一些操作,并将结果添加到数据集中的新列中UDF不使用外部变量[Java spark],java,apache-spark,groovyshell,Java,Apache Spark,Groovyshell,我正在尝试执行以下代码 我将数据集作为输入,使用Groovyshell对其执行一些操作,并将结果添加到数据集中的新列中 private static Dataset<Row> addDebitCreditCol(SparkSession sparkSession,Dataset<Row> df,String code){ Script script=new GroovyShell().parse(code); UDF3 rulesExecu
private static Dataset<Row> addDebitCreditCol(SparkSession sparkSession,Dataset<Row> df,String code){
Script script=new GroovyShell().parse(code);
UDF3 rulesExecutingUDF = (UDF3<Double, String, String, String>) (val1, val2, val3) -> {
Binding binding = new Binding();
binding.setVariable("val1",val1);
binding.setVariable("val2", val2);
binding.setVariable("val3", val3);
Object value = script.run();
return value.toString();
};
sparkSession.udf().register("rulesExecutingUDF",rulesExecutingUDF,DataTypes.StringType);
df=df.withColumn("NEW_COL",callUDF("rulesExecutingUDF",col("val1").,col("val2"),col("val3")));
return df;
}
私有静态数据集addDebitCreditCol(SparkSession SparkSession,数据集df,字符串代码){
Script=newgroovyshell().parse(代码);
UDF3规则执行UDF=(UDF3)(val1、val2、val3)->{
绑定=新绑定();
binding.setVariable(“val1”,val1);
binding.setVariable(“val2”,val2);
binding.setVariable(“val3”,val3);
对象值=script.run();
返回值.toString();
};
sparkSession.udf().register(“rulesExecutingUDF”,rulesExecutingUDF,DataTypes.StringType);
df=带列的df(“新列”),callUDF(“规则执行UDF”,列(“val1”)、列(“val2”)、列(“val3”);
返回df;
}
当我执行这段代码时,它抛出一个错误
用户类引发异常:org.apache.spark.SparkException:任务不可序列化。原因:java.io.NotSerializableException:Script1
看起来我不能在UDF中使用外部变量(这里是脚本)。我还有别的选择吗
我试图让这个外部变量以某种方式工作,但它没有工作,我无法找到一个替代UDF的方法来实现这一点。解决这一问题的简单方法可能是使用一个本身实现可序列化的
public static abstract class BaseClass extends Script implements Serializable {
}
然后将该类用作脚本的超类:
CompilerConfiguration config = new CompilerConfiguration();
config.setScriptBaseClass("stackoverflow.Main.BaseClass"); //use your FQCN
Script script = new GroovyShell(Main.class.getClassLoader(), config).parse(code);
这将使
script
成为可序列化的实例。如果测试基类的脚本实例
和可序列化的脚本实例
,它们都将返回true
解决此问题的简单方法可能是使用实现可序列化的脚本实例本身
public static abstract class BaseClass extends Script implements Serializable {
}
然后将该类用作脚本的超类:
CompilerConfiguration config = new CompilerConfiguration();
config.setScriptBaseClass("stackoverflow.Main.BaseClass"); //use your FQCN
Script script = new GroovyShell(Main.class.getClassLoader(), config).parse(code);
这将使script
成为可序列化的实例。如果测试基类的脚本实例
和可序列化的脚本实例
,它们都将返回true
是否可以尝试移动脚本脚本=新GroovyShell().parse(code)代码>在udf内部?我之前才这么做。但问题是,对于制作新Groovyshell所需的每一条记录,它都会产生一些问题。这就是为什么我必须把它从循环中去掉代码>在udf内部?我之前才这么做。但问题是,对于制作新Groovyshell所需的每一条记录,它都会产生一些问题。这就是为什么我必须把这个从循环中去掉。