繁体   English   中英

通过getter和setter更新pojos的通用方法

[英]Generic way to update pojos via getters and setters

假设我有不同类型的吸气剂和固定剂POJO。 我想写一些通用算法,只需通过lambdas定义getter和setter,就可以将数据从一个更新到另一个。 我试图以这种方式创建它

private static final Map<Function<Entity, Object>, BiConsumer<Entity, Object>> ACCESSORS = new HashMap
        <Function<Entity, Object>, BiConsumer<Entity, Object>>() {{
    put(Entity::getAreaCode, Entity::setAreaCode);
}});

然后我遍历所有应用目标实体的条目,如果getter的结果不为null,那么我想为其他实体应用相应的setter。

但它不起作用,因为Object不能转换为String。 而且我想将它用于不同的类型,不仅是字符串,还有整数等...

是否可以通过一些简单的方法解决而无需创建特殊转换器并将其与每个条目相关联?

使用类似的东西

private static final List<BiConsumer<Entity,Entity>> ACCESSORS =
    Collections.unmodifiableList(Array.asList(
        (src,dst) -> dst.setAreaCode(src.getAreaCode()),
        (src,dst) -> dst.setOtherProperty(src.getOtherProperty())
        /* etc */
));

然后,您可以遍历列表并将每个操作应用于两个实体,例如

static final void copyAll(Entity src, Entity dst) {
    ACCESSORS.forEach(op -> op.accept(src, dst));
}

关键点是实际的属性值类型在每个BiConsumer处理,但不再是通用签名的一部分,因此不需要为ACCESSORS声明。 它更高效,因为它可以处理原始数据类型而无需装箱费用。

无论如何, Map都不适合此任务的数据结构,因为对于这些函数,不能执行有意义的查找,因此这是一个仅用于迭代的数据结构。

您可以将“仅在非空时复制”逻辑与通用帮助程序方法集成:

private static final List<BiConsumer<Entity,Entity>> ACCESSORS =
    Collections.unmodifiableList(Arrays.asList(
        copyWhenNonNull(Entity::getAreaCode, Entity::setAreaCode),
        copyWhenNonNull(Entity::getOtherProperty, Entity::setOtherProperty)
        /* etc */
));
private static <E,V> BiConsumer<E,E> copyWhenNonNull(
    Function<? super E, ? extends V> getter, BiConsumer<? super E, ? super V> setter) {
    return (src,dst) -> {
        V value = getter.apply(src);
        if(value != null) setter.accept(dst, value);
    };
}

copyAll方法不会更改。 这甚至允许混合无条件复制属性,这些属性在条件复制时永远不会为null

我知道你已经有了答案,但是对于将来需要这样的事情的人来说:我已经围绕这个背景开发了一个小型库 - datus

这是一个显示其一些功能的示例:

class Person {
  //getters + setters omitted for brevity
  private String firstName;
  private String lastName;
}

class PersonDTO {
  //getters + setters + empty constructor omitted for brevity
  private String firstName;
  private String lastName;
}

  //the mutable API defines a mapping process by multiple getter-setter steps
  Mapper<Person, PersonDTO> mapper = Datus.forTypes(Person.class, PersonDTO.class).mutable(PersonDTO::new)
      .from(Person::getFirstName).into(PersonDTO.setFirstName)
      .from(Person::getLastName)
      .given(Objects::nonNull, ln -> ln.toUpperCase()).orElse("fallback")
      .into(PersonDTO::setLastName)
      .from(/*...*/).into(/*...*/)
      .build();

  Person person = new Person();
person.setFirstName("firstName");
    person.setLastName(null);
    PersonDTO personDto = mapper.convert(person);
/*
    personDto = PersonDTO [
        firstName = "firstName",
        lastName = "fallback"
    ]
*/
    person.setLastName("lastName");
    personDto = mapper.convert(person);
/*
    personDto = PersonDTO [
        firstName = "firstName",
        lastName = "LASTNAME"
    ]
*/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM