【问题标题】:What is a good way for getter to setter mapping from simple java objects (POJOs). Can is use reflection for it?什么是从简单 Java 对象(PO​​JO)的 getter 到 setter 映射的好方法。可以使用反射吗?
【发布时间】:2019-09-10 21:23:38
【问题描述】:

您好,我有两个相互独立的 java 对象,但共享相同的 gettersetter 方法。例如,我有一个 UserEntityUserDTO 对象,我会将 UserEntity 中的所有 getter 值映射到 UserDTO 的所有 setter。

做这类事情的最佳方法是什么?我更喜欢用 java 反射来做,但我现在也想在外面有一些有用的框架实现。

【问题讨论】:

    标签: java reflection mapping pojo


    【解决方案1】:

    有一个很棒的映射器库,叫做MapStruct,可以用来映射。

    这是您的 UserEntity 和 UserDTO 的示例:

    @Mapper
    public interface UserMapper {
    
        UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
    
        @Mapping
        UserDTO userEntityToUserDTO(UserEntity user); 
    }
    
    UserDTO userDto = UserMapper.INSTANCE.userEntityToUserDTO(userEntity);
    

    它还支持兼容类型之间的转换,如果字段名称不同,还可以设置自定义映射。例如:

    @Mapping(source = "userName", target = "name")
    

    【讨论】:

      【解决方案2】:

      这种需求通常最好使用“转换器”或“映射器”模式来实现。在 Java 中生成映射器的首选工具是 MapStruct,但还有许多其他工具。

      使用反射通常不是最佳选择,因为它速度较慢,而且更难以跟踪和自定义(例如,如果需要在 JSON 中的字符串和 Java 中的 longs 之间转换字段)。

      【讨论】:

        【解决方案3】:

        使用反射和不使用外部库

        您好,您可以检查源对象的所有 getter,并尝试在目标对象上找到所有对应的 setter。以下方法应该做到这一点:

         /**
         * Maps all getter of the source to all corresponding setter of the target
         * @param target
         *      target object which should be set
         * @param source
         *      source object to read from
         * @return
         *      returns mapped target object or null if some error occurred
         */
        private Object getterToSetter(Object target, Object source) {
            try {
                for(Method m: source.getClass().getMethods()){
                    // try to find for all getters in the source the corresponding setter on the target
                    if(m.getName().startsWith("get")){
                        Method setter;
                        try {
                            setter = target.getClass().getMethod("set" + m.getName().substring(3), m.getReturnType());
                            setter.invoke(target,m.invoke(source));
                        } catch (NoSuchMethodException e) {
                            //ignored target just haven't a setter for this field
                        }
                    }
                }
                // return value to support builder pattern
                return target;
            }catch (IllegalAccessException| InvocationTargetException e){
                e.printStackTrace();
            }
            return null;
        }
        

        这是一个完整的 Main.class 示例,说明它是如何工作的:

            import java.lang.reflect.InvocationTargetException;
        import java.lang.reflect.Method;
        
        /**
         * @author Andreas Hauschild
         */
        public class Main {
            public static void main(String[] args) {
                UserEntity userEntity = new UserEntity().setName("Waltraud").setLastName("Schmidt").setPassword("TopSecret");
                UserDTO dto = (UserDTO) getterToSetter(new UserDTO(), userEntity);
                System.out.println(dto.getName());      //  prints "Waltraud"
                System.out.println(dto.getLastName());  //  prints "Schmidt"
            }
        
            /**
             * Maps all getter of the source to all corresponding setter of the target
             * @param target
             *      target object which should be set
             * @param source
             *      source object to read from
             * @return
             *      returns mapped target object or null if some error occurred
             */
            private static Object getterToSetter(Object target, Object source) {
                try {
                    for(Method m: source.getClass().getMethods()){
                        // try to find for all getters in the source the corresponding setter on the target
                        if(m.getName().startsWith("get")){
                            Method setter;
                            try {
                                setter = target.getClass().getMethod("set" + m.getName().substring(3), m.getReturnType());
                                setter.invoke(target,m.invoke(source));
                            } catch (NoSuchMethodException e) {
                                //ignored target just haven't a setter for this field
                            }
                        }
                    }
                    // return value to support builder pattern
                    return target;
                }catch (IllegalAccessException| InvocationTargetException e){
                    e.printStackTrace();
                }
                return null;
            }
        
            public static class UserEntity {
                String password;
                String name;
                String lastName;
        
                public String getPassword() {
                    return password;
                }
        
                public UserEntity setPassword(String password) {
                    this.password = password;
                    return this;
                }
        
                public String getName() {
                    return name;
                }
        
                public UserEntity setName(String name) {
                    this.name = name;
                    return this;
                }
        
                public String getLastName() {
                    return lastName;
                }
        
                public UserEntity setLastName(String lastName) {
                    this.lastName = lastName;
                    return this;
                }
            }
        
            public static class UserDTO {
                String name;
                String lastName;
        
                public String getName() {
                    return name;
                }
        
                public UserDTO setName(String name) {
                    this.name = name;
                    return this;
                }
        
                public String getLastName() {
                    return lastName;
                }
        
                public UserDTO setLastName(String lastName) {
                    this.lastName = lastName;
                    return this;
                }
            }
        
        }
        

        【讨论】:

          猜你喜欢
          • 2016-08-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-10
          • 1970-01-01
          相关资源
          最近更新 更多