Получение так много предупреждений при использовании List с настраиваемым Java-классом POJO в apache beam java
Я новичок в Apache beam, я использую луч Apache и в качестве бегуна использую поток данных в GCP. Я получаю следующую ошибку при выполнении конвейера.
coder of type class org.apache.beam.sdk.coders.ListCoder has a #structuralValue method which does not return true when the encoding of the elements is equal. Element [Person [businessDay=01042020, departmentId=101, endTime=2020-04-01T09:06:02.000Z, companyId=242, startTime=2020-04-01T09:00:33.000Z], Person [businessDay=01042020, departmentId=101, endTime=2020-04-01T09:07:47.000Z, companyId=242, startTime=2020-04-01T09:06:03.000Z], Person [businessDay=01042020, departmentId=101, endTime=2020-04-01T09:48:25.000Z, companyId=242, startTime=2020-04-01T09:07:48.000Z]]
PCollection похож на PCollection
Я реализовал Person как сериализуемый класс POJO и также переопределил метод equals и hash. Но я думаю, что мне нужно написать собственный ListCoder для человека и зарегистрироваться в конвейере. Я не знаю, как решить эту проблему, пожалуйста, помогите.
1 ответ
Вот рабочий пример. Если вы клонируете репо, подplayground
корневой каталог, запустить ./gradlew run
, тогда вы можете проверить эффект. Вы также можете работать с./gradlew run --args='--runner=DataflowRunner --project=$YOUR_PROJECT_ID --tempLocation=gs://xxx/staging --stagingLocation=gs://xxx/staging'
чтобы запустить его в Dataflow.
В Person
class должен выглядеть так, если вы строите его с нуля:
class Person implements Serializable {
public Person(
String businessDay,
String departmentId,
String companyId
) {
this.businessDay = businessDay;
this.departmentId = departmentId;
this.companyId = companyId;
}
public String companyId() {
return companyId;
}
public String businessDay() {
return businessDay;
}
public String departmentId() {
return departmentId;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (other == null) {
return false;
}
if (getClass() != other.getClass()) {
return false;
}
Person otherPerson = (Person) other;
return this.businessDay.equals(otherPerson.businessDay)
&& this.departmentId.equals(otherPerson.departmentId)
&& this.companyId.equals(otherPerson.companyId);
}
@Override
public int hashCode(){
return Objects.hash(this.businessDay, this.departmentId, this.companyId);
}
private final String businessDay;
private final String departmentId;
private final String companyId;
}
я рекомендую
использование AutoValue вместо создания POJO с нуля. Вот несколько примеров. Вы можете просмотреть весь проект здесь. Преимущество в том, что вам не нужно реализовывать
equals
а такжеhashCode
с нуля каждый раз, когда вы создаете новый тип объекта.В KV, если ключ является итерируемым, например List, оберните его в объект и явно детерминированно сериализуйте его (пример), поскольку сериализация в Java недетерминирована.