【问题标题】:Copy POJO content from one bean to another将 POJO 内容从一个 bean 复制到另一个
【发布时间】:2011-05-09 13:30:43
【问题描述】:

我在不同的包中有几个 Pojo,每个 POJO 包含来自同一个包的另一个 pojo 的集合。我需要将包 B Pojos 中的所有同名项目复制到包 A 中的对象。

示例:

package com.vanilla.packageA;

public class Student{

    private String firstName;
    private String lastName;
    private Set<Course> course;

    //getters and setters ommited

}   

package com.vanilla.packageA;

    public class Course{
    private String courseName;
    private String courseDescription;

    //seters and getters
}

package com.vanilla.packageB;

public class Student{

    private String firstName;
    private String lastName;
    private Address address;
    private Set<Course> course;
    Private Date birtday;

    //getters and setters ommited

}   

package com.vanilla.packageB;

public class Course{
    private String courseName;
    private String courseDescription;
    private <Lecturer> lecturer;
    private Integer hours;

    //seters and getters
} 

我想将 PackageB 类中的所有项目递归复制到 packageA 类中存在的 PaCkageB 并共享相同的名称。

更新:

伙计们,我知道这是个愚蠢的问题,但我需要维护这段代码,现在代码的编写方式是他们必须调用 50 个 getter 和 setter,或者调用带有 50 个参数的构造函数。 不幸的是,我不能使用同一个对象,我需要复制它,但我必须找到更“优雅”的方式来复制 tese beans。

【问题讨论】:

  • 似乎是一个奇怪的请求。您是否需要访问受保护或默认的方法/变量?
  • 我有getter和setter,所以我可以使用它。
  • 我会说你有一个 POJO 或一个 Bean。 “POJO 是 Plain Old Java Object 的首字母缩写词。该名称用于强调给定对象是普通 Java 对象,而不是特殊对象,尤其不是 Enterprise JavaBean。”来自 POJO 的维基百科条目
  • 如果您不需要访问包范围的东西,那么为什么不直接使用包 B 中的类呢?没有理由需要将类放在包 A 中。
  • 请看我的更新,它会解释更多。

标签: java apache-commons


【解决方案1】:

Apache BeanUtils.copyProperties 不起作用的任何原因?

【讨论】:

  • apache BeanUtils 会复制不同类的项目吗?我总是用它来复制同一类的相同pojo。
  • 实际上它确实有效,前提是两个类具有相同的 getter 和 setter。
  • BeanUtils 不会做深拷贝。所以嵌套bean等不起作用(奇怪)。
  • Beanutils 有第三方问题,你知道其他替代方案吗?
【解决方案2】:

嗯..Dozer 可能正是您要找的东西。

。 . .它是一个对象到对象映射框架。这个想法是:

  • 通常它会按照惯例进行映射。
  • 您可以使用映射文件覆盖此约定。

。 .因此映射文件尽可能紧凑。它在许多情况下都很有用,例如将用例指定的服务负载映射到可重用的核心模型对象上。

在提供 SpringSource 培训课程时,我们经常会指出这个框架。

【讨论】:

    【解决方案3】:

    请参阅mapstruct。该工具生成代码,因此没有反射开销。

    【讨论】:

      【解决方案4】:

      如果你已经有 spring 依赖,你可以使用org.springframework.beans.BeanUtils

      BeanUtils.copyProperties(from, to);
      

      【讨论】:

      • 如果我的属性在不同的情况下,有什么选择吗?
      【解决方案5】:

      几乎每个项目都需要复制字段值,例如克隆()。我还认为,为了完成某些目标,不需要导入 .jars 来仅使用一个功能。我想分享一些我正在工作的小代码,有些东西我留在了墨水瓶中,但总的来说它可以完成工作。在这种情况下,我使用反射。

      public class ObjectCopyTools {
      
      static String[] bases = new String[] {"byte", "short", "int", "long", "float", "double", "char", "boolean"};
      static String[] equivalents = new String[] {"Byte", "Short", "Integer", "Long", "Float", "Double", "Character", "Boolean"};
      
      static {
      
      }
      
      private static boolean areEquivalents(String type1, String type2){
          for (int i = 0; i < bases.length; i++) {
              if((type1.equals(bases[i]) && type2.equals(equivalents[i])) 
                      || (type2.equals(bases[i]) && type1.equals(equivalents[i]))){
                  return true;
              }
          }
          return false;
      }
      
      public static <T extends Object, Y extends Object> Y deepReflectionObjectCopy(T origin, Class<Y> resultClass) {
          Class<? extends Object> origClass = origin.getClass();
          Y resultObject = null;
          for (Constructor<?> constructor : resultClass.getConstructors()) {
              if (constructor.getParameterCount() == 0) {
                  try {
                      resultObject = (Y) constructor.newInstance();
                  }catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                  }
                  break;
              }
          }
          if(resultObject == null){
              return null;
          }
          Field[] origFields = origClass.getDeclaredFields();
          Field[] destFields = resultObject.getClass().getDeclaredFields();
      
          Object value = null;
          for(Field dstField: destFields){
              try {
                  Field tempOrigField = origClass.getDeclaredField(dstField.getName());
                  if(tempOrigField.getType().equals(dstField.getType())
                          || areEquivalents(tempOrigField.getType().getSimpleName(), dstField.getType().getSimpleName())){
                      dstField.set(resultObject, tempOrigField.get(origin));
                  }
              } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
              }
          }
          return resultObject;
      }
      

      希望对您有所帮助。

      【讨论】:

      • 您是否忘记添加任何代码,这不起作用 - 我试过但找不到丢失的内容
      • 这段代码对我有用,是通用代码,没有任何特殊或缺失的代码。您能否更具体地说明为什么对您不起作用?
      【解决方案6】:

      如果 DRY 是计算机科学的基石原则,你能给出两个相同的平行对象图的理由是什么?不仅您的维护负担增加了一倍,而且现在您必须开发一种递归方法,除了将数据从一个传送到另一个之外什么都不做。

      【讨论】:

      • 不幸的是,这段代码不是我设计的,我现在只是维护它。目前,他们正在使用从其他类获得的具有 50 个参数的构造函数。 :)
      • 一个例子是由 web 服务生成的代码。在我的代码中,我必须使用 getCustomerById() 按 ID 请求对象,然后要更新它,我必须调用 setCustomer(CustomerUpdateRequest)。 getCustomerId 返回一个 CustomerResponse - 里面的所有字段都是 Strings/ints/longs,或者是 AddressResponse 之类的东西。 CustomerUpdateRequest 包含 Strings/ints/longs 和 AddressRequest,但所有字段名称都相同,无止境!
      【解决方案7】:

      使用 PropertyUtils,您可以复制 onky 非空属性,如下所示:

          private void copyNonNullProperties(Object destination,
                  Object source) {
              try {
                  PropertyUtils.describe(source).entrySet().stream()
                          .filter(source -> source.getValue() != null)
                          .filter(source -> !source.getKey().equals("class"))
                          .forEach(source -> {
                              try {
                                  PropertyUtils.setProperty(destination, source.getKey(), source.getValue());
                              } catch (Exception e22) {
                                  log.error("Error setting properties : {}", e22.getMessage());
                              }
                          });
      
              } catch (Exception e1) {
                  log.error("Error setting properties : {}", e1.getMessage());
              }
      
          }
      

      【讨论】:

        【解决方案8】:

        您是否尝试过使用BULL?您可以在DZone 上找到有关如何使用它的指南。它提供了在应对时也执行对象转换的可能性。 此外,它递归地执行复制,不需要定义 getter 和 setter。

        【讨论】:

          猜你喜欢
          • 2019-09-06
          • 1970-01-01
          • 2014-04-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-15
          • 1970-01-01
          相关资源
          最近更新 更多