0x0 Dataset转POJO
方法:
- 将查询出的结果转为RDD
- 将RDD创建为DataFrame,并传入schema参数
- 调用as方法,将Dataset转为相应的POJO Dataset
- 调用collectAsList()方法
代码如下:
1.表结构
+--------+---------+-------+
|col_name|data_type|comment|
+--------+---------+-------+
| id| string| null|
| name| string| null|
| class| string| null|
+--------+---------+-------+
2.POJO类
public class Student {
String id;
String name;
String major;
...
}
3.转换代码
SparkSession spark = CloudUtils.getSparkSession();
// 查询原始数据
Dataset<Row> student = spark.sql("select * from `event`.`student`");
// 生成schema
List<StructField> fields = new ArrayList<>();
fields.add(DataTypes.createStructField("id", DataTypes.StringType, true));
fields.add(DataTypes.createStructField("name", DataTypes.StringType, true));
fields.add(DataTypes.createStructField("major", DataTypes.StringType, true));
StructType schema = DataTypes.createStructType(fields);
// 转换查询结果为POJO List
List<Student> students = spark.createDataFrame(student.toJavaRDD(), schema)
.as(Encoders.bean(Student.class))
.collectAsList();
System.out.println(students);
注意:
Dataset中的日期类型为timestamp和java中的Date类型不兼容,和Timestamp类型相互兼容。
为了解决上述问题,我们可以先将Dataset转为JSON,然后将JSON转为POJO,代码如下:
// 查出数据并转为json集合
List<String> jsonList = spark.sql("select * from `event`.`user`")
.toJSON()
.collectAsList();
// 将json转为pojo,这里使用的是FastJSON
List<User> users = jsonList.stream()
.map(jsonString -> JSON.parseObject(jsonString, User.class))
.collect(Collectors.toList());
System.out.println(users);
0x1 POJO转Dataset
1.表结构
+---------+---------+-------+
|col_name |data_type|comment|
+---------+---------+-------+
| user_id | string| null|
|user_name| string| null|
|user_age | int | null|
+---------+---------+-------+
2.POJO类
public class User{
String userId;
String userName;
Integer userAge;
...
}
转换代码:
// 获取users列表
List<User> users = createUsers();
// 使用createDataFrame转为dataset
Dataset<Row> ds = spark.createDataFrame(users, User.class);
// 将驼峰式列名改为下划线式列名,camelToUnderline方法网上搜索
String[] columns = ds.columns();
String[] newColumns = Arrays.stream(columns)
.map(column -> camelToUnderline(column))
.toArray(String[]::new);
// 转为新的df(重命名后的)
ds.toDF(newColumns);
ds.show();
同样注意:
对于有些类型无法转换的情况,仍然采用json过渡,代码如下:
// 创建user list
List<User> users = createUsers();
// 将user list转为json list
List<String> jsonList = users.stream()
.map(JSON::toJSONString)
.collect(Collectors.toList());
// 将json list转为json dataset
Dataset<String> jsonDataset = spark.createDataset(jsonList, Encoders.STRING());
// 转换为row dataset
Dataset<Row> ds = spark.read().json(jsonDataset.toJavaRDD());
ds.show();
输出结果:
+------------+---+----+
| birthday| id|name|
+------------+---+----+
|689875200000| 1| AAA|
|689875200000| 2| BBB|
+------------+---+----+