Java反射:为集合类型Object调用Setter和Getter方法

时间:2016-01-22 10:44:07

标签: java reflection mapping

我有两个不同的用户定义对象包....

1) ws.lender.dto (all Objects exists in this package are source side).
2) copl.com.dto (all Objects exists in this package are destination side).

对象层次结构和对象名称在两侧都不同。我想去  按源或复制源端对象到目标端对象  使用反射通过getter和setter。

例如

来源对象

   package ws.lender.dto;

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "CustomerAddresses", propOrder = {
        "previousAddresses"
    })
    public class CustomerAddresses {

        protected PreviousAddresses previousAddresses;

        public PreviousAddresses getPreviousAddresses() {
            return previousAddresses;
        }

        public void setPreviousAddresses(PreviousAddresses value) {
            this.previousAddresses = value;
        }

    }


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PreviousAddresses", propOrder = {
    "previousAddress"
})
public class PreviousAddresses {

    @XmlElement(name = "PreviousAddress", required = true)
    protected List<PreviousAddress> previousAddress;

    public List<PreviousAddress> getPreviousAddress() {
        if (previousAddress == null) {
            previousAddress = new ArrayList<PreviousAddress>();
        }
        return this.previousAddress;
    }
}


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PreviousAddress", propOrder = {

    "streetNo",
    "streetName"
})
public class PreviousAddress {

    @XmlElement(name = "StreetNo", required = true)
    protected String streetNo;
    @XmlElement(name = "StreetName", required = true)
    protected String streetName;

    public String getStreetNo() {
        return streetNo;
    }
    public void setStreetNo(String value) {
        this.streetNo = value;
    }
    public String getStreetName() {
        return streetName;
    }
    public void setStreetName(String value) {
        this.streetName = value;
    }
}

目的地方对象

package copl.com.dto;

@javax.persistence.Entity
public class Customer implements java.io.Serializable
{
private Set<CustomerAddress> customerAddresses;

   public Set<CustomerAddress> getCustomerAddresses()
    {
        return customerAddresses;
    }

        public void setCustomerAddresses(Set<CustomerAddress> customerAddresses)
    {
        this.customerAddresses = customerAddresses;
    }
}

@javax.persistence.Entity
public class CustomerAddress implements java.io.Serializable
{   
    private String unitNumber;
    private String streetName;
    private String streetNumber;

   public String getUnitNumber()
    {
        return unitNumber;
    }   
        public void setUnitNumber(String unitNumber)
    {
        this.unitNumber = unitNumber;
    }
        public String getStreetName()
    {
        return streetName;
    }
       public String getStreetNumber()
    {
        return streetNumber;
    }
        public void setStreetName(String streetName)
    {
        this.streetName = streetName;
    }

    public void setStreetNumber(String streetNumber)
    {
        this.streetNumber = streetNumber;
    }
}   

4 个答案:

答案 0 :(得分:8)

我认为你可以使用MapStruct来映射具有不同属性名称的POJO。

但您的方案很复杂,因为您希望将ws.lender.dto.CustomerAddresses转换为copl.com.dto.Customer,这意味着将包含在List<ws.lender.dto.PreviousAddress>内的ws.lender.dto.PreviousAddresses转换为Set<copl.com.dto.CustomerAddress> {1}}包含在copl.com.dto.Customer对象中。

所以,我将逐步解释。

1。从ws.lender.dto.PreviousAddress转换为copl.com.dto.CustomerAddress

要进行此转换,您需要一个接口(MapStruct将为此创建一个实例),负责从源对象到目标对象的映射:

import ws.lender.dto.PreviousAddress;
import copl.com.dto.CustomerAddress;

@Mapper
public interface CustomerAddressesMapper{

    CustomerAddressesMapper INSTANCE = Mappers.getMapper( CustomerAddressesMapper.class );

    @Mappings(@Mapping(source = "streetNo", target = "streetNumber")
    CustomerAddress previousToCustomerObject(PreviousAddress address);
}

考虑到PreviousAddress属性必须映射到CustomerAddress,此界面会将streetNo对象映射到streetNumberunitNumber属性没有映射,因为它没有源。

2。将List<ws.lender.dto.PreviousAddress>转换为Set<copl.com.dto.CustomerAddress>

现在您必须向现有CustomerAddressesMapper接口添加另一种映射方法:

Set<CustomerAddress> previousToCustomerSet(List<PreviousAddress> addresses);

此方法将使用前一个previousToCustomerObject将源列表的每个元素转换为目标集。

3。从ws.lender.dto.CustomerAddresses转换为copl.com.dto.Customer

最后,您需要将最后一个映射方法添加到CustomerAddressesMapper接口:

@Mappings(@Mapping(source = "previousAddresses.previousAddress", target = "customerAddresses")
Customer customerAddrsToCustomerObject(CustomerAddresses addresses);

这是您使用以前的方法映射原始对象,将previousAddresses.previousAddress属性转换为customerAddresses属性的位置。

4。使用映射器

要使用映射器,您必须编写如下代码:

CustomerAddressesMapper mapper = CustomerAddressesMapper.INSTANCE;
CustomerAddresses origin = //Retrieve it from anywhere
Customer dest = mapper.customerAddrsToCustomerObject(origin);

5。设置

MapStruct是一个源代码生成器,因此您需要正确配置pom.xml以包含MapStruct依赖项并调用此代码生成。您可以看到如何执行此操作here

我没有构建和运行此代码,但这是实现此目的的方法。

希望它有所帮助!

答案 1 :(得分:3)

我已经为这个作业研究了很多对象映射框架,比如

最后,我选择Orika框架来完成上面的Objects to Objects映射。我们可以通过其他映射器框架进行映射,但我就像Orika框架,因为这个框架非常容易用于将对象映射到对象。

我将逐步解释。

<强> 1。创建源侧对象和目标端对象的对象。

像这样......

    Customer destination = new Customer();
    CustomerAddresses source = new CustomerAddresses();
    source = filledCustomerAddressesObject();

<强> 2。构造DefaultMapperFactory

MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

第3。映射字段

    ClassMapBuilder<CustomerAddresses, Customer> builder;

    builder= mapperFactory.classMap(CustomerAddresses.class, Customer.class).constructorA();

    builder.field("previousAddresses.previousAddress{streetNo}","customerAddresses{streetNumber}");
    builder.field("previousAddresses.previousAddress{streetName}","customerAddresses{streetName}");

    builder.register();

    BoundMapperFacade<CustomerAddresses, Customer> boundMapper;

    boundMapper = mapperFactory.getMapperFacade(CustomerAddresses.class, Customer.class);

    destination = boundMapper.map(source, destination);

它的工作很好干杯

答案 2 :(得分:2)

您可以更好地尝试Object Mapper进行投射或复制。对于其他包中的其他类的对象,您可以添加一些属性值,如

  

senderClass rvcClass

稍后您可以阅读这些属性并继续转换该类。可能你已经准备好发送者类与接收者类的映射。

答案 3 :(得分:1)

如果我理解正确,您需要一种方法将所有同名的属性从一个对象复制到另一个对象。类似命名的属性可能是源对象有一个名为getPropertyName()的方法,而目标对象有一个名为setPropertyName()的情况。

如果这是正确的,那么您希望使用Apache Commons库中的BeanUtils类的copyProperties方法。文档为here

现在,在您的示例中,您有一些不相似的相应属性,例如StreetNumber和StreetNo。我担心通过反思自动处理这类事情并不容易;您需要自己定义源属性和目标属性之间的映射,可能通过定义辅助类来进行复制。