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

时间:2022-09-24 18:48:13

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。

8 个解决方案

#1


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接口。

#2


I had the same problem when developing an app for Google App Engine, where I couldn't use BeanUtils due to commons Logging restrictions. Anyway, I came up with this solution and worked just fine for me.

在为Google App Engine开发应用程序时遇到了同样的问题,由于公共日志限制,我无法使用BeanUtils。无论如何,我提出了这个解决方案,并为我工作得很好。

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.

任何增强或推荐都非常受欢迎。

#3


Hey friends just use my created ReflectionUtil class for copy one bean values to another similar bean. This class will also copy Collections object.

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

嘿朋友们只是使用我创建的ReflectionUtil类将一个bean值复制到另一个类似的bean。该类还将复制Collections对象。 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. If one entity has another entity in it then you can pass map option for runtime change of inner entity to its related bean.

现在增加了更多功能。您还可以将一个实体数据复制到其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.

当您的实体包含关系时,此案例非常有用。

#4


Have a look at the JavaBeans API, in particular the Introspector class. You can use the BeanInfo metadata to get and set properties. It is a good idea to read up on the JavaBeans specification if you haven't already. It also helps to have a passing familiarity with the reflection API.

查看JavaBeans API,特别是Introspector类。您可以使用BeanInfo元数据来获取和设置属性。如果您还没有阅读JavaBeans规范,那么这是一个好主意。它也有助于熟悉反射API。

#5


Another alternative is MapStruct which generates mapping code at build time, resulting in type-safe mappings which don't require any dependencies at runtime (Disclaimer: I'm the author of MapStruct).

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

#6


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. 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.

没有简单的方法可以做到这一点。 Introspector和Java bean库是单片的 - BeanUtils是一个简单的包装器并且运行良好。没有库只是为了没有库通常是一个坏主意 - 这是一个共同的原因 - Java应该存在的常见功能,但不是。

#7


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);
    }
}

#8


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);
    }
}

#1


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接口。

#2


I had the same problem when developing an app for Google App Engine, where I couldn't use BeanUtils due to commons Logging restrictions. Anyway, I came up with this solution and worked just fine for me.

在为Google App Engine开发应用程序时遇到了同样的问题,由于公共日志限制,我无法使用BeanUtils。无论如何,我提出了这个解决方案,并为我工作得很好。

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.

任何增强或推荐都非常受欢迎。

#3


Hey friends just use my created ReflectionUtil class for copy one bean values to another similar bean. This class will also copy Collections object.

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

嘿朋友们只是使用我创建的ReflectionUtil类将一个bean值复制到另一个类似的bean。该类还将复制Collections对象。 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. If one entity has another entity in it then you can pass map option for runtime change of inner entity to its related bean.

现在增加了更多功能。您还可以将一个实体数据复制到其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.

当您的实体包含关系时,此案例非常有用。

#4


Have a look at the JavaBeans API, in particular the Introspector class. You can use the BeanInfo metadata to get and set properties. It is a good idea to read up on the JavaBeans specification if you haven't already. It also helps to have a passing familiarity with the reflection API.

查看JavaBeans API,特别是Introspector类。您可以使用BeanInfo元数据来获取和设置属性。如果您还没有阅读JavaBeans规范,那么这是一个好主意。它也有助于熟悉反射API。

#5


Another alternative is MapStruct which generates mapping code at build time, resulting in type-safe mappings which don't require any dependencies at runtime (Disclaimer: I'm the author of MapStruct).

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

#6


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. 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.

没有简单的方法可以做到这一点。 Introspector和Java bean库是单片的 - BeanUtils是一个简单的包装器并且运行良好。没有库只是为了没有库通常是一个坏主意 - 这是一个共同的原因 - Java应该存在的常见功能,但不是。

#7


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);
    }
}

#8


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);
    }
}