【问题标题】:Java Reflection: Invoking Setter and Getter method for collection type ObjectJava 反射:为集合类型 Object 调用 Setter 和 Getter 方法
【发布时间】:2016-04-28 22:31:09
【问题描述】:

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

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

【问题讨论】:

  • @MadProgrammer 我需要你的帮助。

标签: java reflection mapping


【解决方案1】:

我研究了很多对象映射框架来完成这个任务,比如

最后我选择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】:

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

    senderClassrvcClass

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

    【讨论】:

    【解决方案3】:

    我认为您可以使用MapStruct 在具有不同属性名称的 POJO 之间进行映射。

    但是您的情况很复杂,因为您想将ws.lender.dto.CustomerAddresses 转换为copl.com.dto.Customer,这意味着将包含在ws.lender.dto.PreviousAddresses 对象中的List&lt;ws.lender.dto.PreviousAddress&gt; 转换为包含在copl.com.dto.Customer 中的Set&lt;copl.com.dto.CustomerAddress&gt;对象。

    所以,我会一步一步解释。

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

    考虑到streetNo 属性必须映射到streetNumber,此接口会将PreviousAddress 对象映射到CustomerAddressunitNumber 属性没有映射,因为它没有来源。

    2。将List&lt;ws.lender.dto.PreviousAddress&gt; 转换为Set&lt;copl.com.dto.CustomerAddress&gt;

    现在您必须向现有的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

    好吧,我不构建和运行这段代码,但这是实现它的方法。

    希望对你有帮助!

    【讨论】:

    • 非常感谢您花时间回答这个问题,我尝试使用上述但没有成功,然后我已经转移到 orika mapper 框架并且我已经完成了工作。但最后我决定把赏金奖励给你。
    • @Z.I.J,出于兴趣,您遇到了哪些具体问题?很高兴了解更多细节,也许我们可以在 MapStruct 中改进一些东西。谢谢!
    【解决方案4】:

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

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

    现在,在您的示例中,您有一些名称不同的对应属性,例如 StreetNumber 和 StreetNo。恐怕没有简单的方法可以通过反射自动处理这类事情。您需要自己定义源属性和目标属性之间的映射,可能通过定义一个帮助类来进行复制。

    【讨论】:

    • 非常感谢您对我的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-09
    • 2016-08-03
    • 1970-01-01
    • 2012-12-12
    相关资源
    最近更新 更多