简体   繁体   English

如何将属性从一个Java bean复制到另一个?

[英]How to copy properties from one Java bean to another?

I have a simple Java POJO that I would copy properties to another instance of same POJO class. 我有一个简单的Java POJO,我将属性复制到同一个POJO类的另一个实例。

I know I can do that with BeanUtils.copyProperties() but I would like to avoid use of a third-party library. 我知道我可以用BeanUtils.copyProperties()做到这一点,但我想避免使用第三方库。

So, how to do that simply, the proper and safer way ? 那么,如何简单地,正确和安全的方式呢?

By the way, I'm using Java 6. 顺便说一下,我正在使用Java 6。

I guess if you look at the source code of BeanUtils, it will show you how to do this without actually using BeanUtils. 我想如果你看一下BeanUtils的源代码,它会告诉你如何在不使用BeanUtils的情况下做到这一点。

If you simply want to create a copy of a POJO (not quite the same thing as copying the properties from one POJO to another), you could change the source bean to implement the clone() method and the Cloneable interface. 如果您只是想创建POJO的副本(与将属性从一个POJO复制到另一个POJO不完全相同),您可以更改源bean以实现clone()方法和Cloneable接口。

I had the same problem when developing an app for Google App Engine, where I couldn't use BeanUtils due to commons Logging restrictions. 在为Google App Engine开发应用程序时遇到了同样的问题,由于公共日志限制,我无法使用BeanUtils。 Anyway, I came up with this solution and worked just fine for me. 无论如何,我提出了这个解决方案,并为我工作得很好。

public static void copyProperties(Object fromObj, Object toObj) {
    Class<? extends Object> fromClass = fromObj.getClass();
    Class<? extends Object> toClass = toObj.getClass();

    try {
        BeanInfo fromBean = Introspector.getBeanInfo(fromClass);
        BeanInfo toBean = Introspector.getBeanInfo(toClass);

        PropertyDescriptor[] toPd = toBean.getPropertyDescriptors();
        List<PropertyDescriptor> fromPd = Arrays.asList(fromBean
                .getPropertyDescriptors());

        for (PropertyDescriptor propertyDescriptor : toPd) {
            propertyDescriptor.getDisplayName();
            PropertyDescriptor pd = fromPd.get(fromPd
                    .indexOf(propertyDescriptor));
            if (pd.getDisplayName().equals(
                    propertyDescriptor.getDisplayName())
                    && !pd.getDisplayName().equals("class")) {
                 if(propertyDescriptor.getWriteMethod() != null)                
                         propertyDescriptor.getWriteMethod().invoke(toObj, pd.getReadMethod().invoke(fromObj, null));
            }

        }
    } catch (IntrospectionException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}

Any enhancements or recomendations are really welcome. 任何增强或推荐都非常受欢迎。

另一种选择是MapStruct ,它在构建时生成映射代码,从而产生类型安全的映射,在运行时不需要任何依赖(免责声明:我是MapStruct的作者)。

Hey friends just use my created ReflectionUtil class for copy one bean values to another similar bean. 嘿朋友们只是使用我创建的ReflectionUtil类将一个bean值复制到另一个类似的bean。 This class will also copy Collections object. 该类还将复制Collections对象。

https://github.com/vijayshegokar/Java/blob/master/Utility/src/common/util/reflection/ReflectionUtil.java https://github.com/vijayshegokar/Java/blob/master/Utility/src/common/util/reflection/ReflectionUtil.java

Note: This bean must have similar variables name with type and have getter and setters for them. 注意:此bean必须具有类似的变量名称,并且具有getter和setter。

Now more functionalities are added. 现在增加了更多功能。 You can also copy one entity data to its bean. 您还可以将一个实体数据复制到其bean。 If one entity has another entity in it then you can pass map option for runtime change of inner entity to its related bean. 如果一个实体中有另一个实体,那么您可以将内部实体的运行时更改的map选项传递给其相关的bean。

Eg. 例如。

ParentEntity parentEntityObject = getParentDataFromDB();
Map<Class<?>, Class<?>> map = new HashMap<Class<?>, Class<?>>();
map.put(InnerBean1.class, InnerEntity1.class);
map.put(InnerBean2.class, InnerEntity2.class);
ParentBean parent = ReflectionUtil.copy(ParentBean.class, parentEntityObject, map);

This case is very useful when your Entities contains relationship. 当您的实体包含关系时,此案例非常有用。

Have a look at the JavaBeans API , in particular the Introspector class. 查看JavaBeans API ,特别是Introspector类。 You can use the BeanInfo metadata to get and set properties. 您可以使用BeanInfo元数据来获取设置属性。 It is a good idea to read up on the JavaBeans specification if you haven't already. 如果您还没有阅读JavaBeans规范,那么这是一个好主意。 It also helps to have a passing familiarity with the reflection API . 它也有助于熟悉反射API

There is no simple way to do it. 没有简单的方法来做到这一点。 Introspector and the Java beans libraries are monolithic - BeanUtils is a simple wrapper around this and works well. Introspector和Java bean库是单片的 - BeanUtils是一个简单的包装器并且运行良好。 Not having libraries just to not have libraries is a bad idea in general - there's a reason it's commons to begin with - common functionality that should exist with Java, but doesn't. 没有库只是没有库通常是一个坏主意 - 有一个原因是它的开头 - Java应该存在的常见功能,但不是。

I ran into some problems with Introspector.getBeanInfo not returning all the properties, so I ended up implementing a field copy instead of property copy. 我遇到了一些Introspector.getBeanInfo没有返回所有属性的问题,所以我最终实现了一个字段副本而不是属性副本。

public static <T> void copyFields(T target, T source) throws Exception{
    Class<?> clazz = source.getClass();

    for (Field field : clazz.getFields()) {
        Object value = field.get(source);
        field.set(target, value);
    }
}

You can achieve it using Java Reflection API . 您可以使用Java Reflection API实现它。

public static <T> void copy(T target, T source) throws Exception {
    Class<?> clazz = source.getClass();

    for (Field field : clazz.getDeclaredFields()) {
        if (Modifier.isPrivate(field.getModifiers()))
            field.setAccessible(true);
        Object value = field.get(source);
        field.set(target, value);
    }
}

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

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