How to ignore null values using springframework BeanUtils copyProperties?

后端 未结 6 1315
悲哀的现实
悲哀的现实 2020-12-01 00:09

I would like to know how to copy the properties from an Object Source to an Object Dest ignoring null values​​ using Spring Framework.

I actually use Apache beanutil

相关标签:
6条回答
  • 2020-12-01 00:43

    SpringBeans.xml

    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
        <bean id="source" class="com.core.HelloWorld">
            <property name="name" value="Source" />
            <property name="gender" value="Male" />
        </bean>
    
        <bean id="target" class="com.core.HelloWorld">
            <property name="name" value="Target" />
        </bean>
    
    </beans>
    
    1. Create a java Bean,

      public class HelloWorld {
          private String name;
          private String gender;
      
          public void printHello() {
              System.out.println("Spring 3 : Hello ! " + name + "    -> gender      -> " + gender);
          }
      
          //Getters and Setters
      }
      
    2. Create Main Class to test

      public class App {
          public static void main(String[] args) {
              ApplicationContext context = new ClassPathXmlApplicationContext("SpringBeans.xml");
      
              HelloWorld source = (HelloWorld) context.getBean("source");
              HelloWorld target = (HelloWorld) context.getBean("target");
      
              String[] nullPropertyNames = getNullPropertyNames(target);
              BeanUtils.copyProperties(target,source,nullPropertyNames);
              source.printHello();
          }
      
          public static String[] getNullPropertyNames(Object source) {
              final BeanWrapper wrappedSource = new BeanWrapperImpl(source);
              return Stream.of(wrappedSource.getPropertyDescriptors())
                  .map(FeatureDescriptor::getName)
                  .filter(propertyName -> wrappedSource.getPropertyValue(propertyName) == null)
                  .toArray(String[]::new);
          }
      }
      
    0 讨论(0)
  • 2020-12-01 00:43

    I advise you to use ModelMapper.

    This is a sample code that solves your doubt.

          ModelMapper modelMapper = new ModelMapper();
    modelMapper.getConfiguration().setSkipNullEnabled(true).setMatchingStrategy(MatchingStrategies.STRICT);
    
          Company a = new Company();
          a.setId(123l);
          Company b = new Company();
          b.setId(456l);
          b.setName("ABC");
    
          modelMapper.map(a, b);
    
          System.out.println("->" + b.getName());
    

    It should print the B value. But if you set the "A" name, the result is a print of "A" value.

    The secret is changing the value of SkipNullEnabled to true.

    ModelMapper

    ModelMapper MVN

    0 讨论(0)
  • 2020-12-01 00:50

    Java 8 version of getNullPropertyNames method from alfredx's post:

    public static String[] getNullPropertyNames(Object source) {
        final BeanWrapper wrappedSource = new BeanWrapperImpl(source);
        return Stream.of(wrappedSource.getPropertyDescriptors())
                .map(FeatureDescriptor::getName)
                .filter(propertyName -> wrappedSource.getPropertyValue(propertyName) == null)
                .toArray(String[]::new);
    }
    
    0 讨论(0)
  • 2020-12-01 01:01

    A better solution based on Pawel Kaczorowski's answer:

    public static String[] getNullPropertyNames(Object source) {
        final BeanWrapper wrappedSource = new BeanWrapperImpl(source);
        return Stream.of(wrappedSource.getPropertyDescriptors())
            .map(FeatureDescriptor::getName)
            .filter(propertyName -> {
                try {
                   return wrappedSource.getPropertyValue(propertyName) == null
                } catch (Exception e) {
                   return false
                }                
            })
            .toArray(String[]::new);
    }
    

    For example, if we have a DTO:

    class FooDTO {
        private String a;
        public String getA() { ... };
        public String getB();
    }
    

    Other answers will throw exceptions on this special case.

    0 讨论(0)
  • 2020-12-01 01:02

    You can create your own method to copy properties while ignoring null values.

    public static String[] getNullPropertyNames (Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();
    
        Set<String> emptyNames = new HashSet<String>();
        for(java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) emptyNames.add(pd.getName());
        }
    
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }
    
    // then use Spring BeanUtils to copy and ignore null using our function
    public static void myCopyProperties(Object src, Object target) {
        BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
    }
    
    0 讨论(0)
  • 2020-12-01 01:07
    public static List<String> getNullProperties(Object source) {
        final BeanWrapper wrappedSource = new BeanWrapperImpl(source);
        return Stream.of(wrappedSource.getPropertyDescriptors())
            .map(FeatureDescriptor::getName)
            .filter(propertyName -> Objects.isNull(wrappedSource.getPropertyValue(propertyName)))
            .collect(Collectors.toList());
    
    0 讨论(0)
提交回复
热议问题