当前位置: 首页 > 工具软件 > Orika > 使用案例 >

orika 映射非空字段_Orika:将JAXB对象映射到业务/域对象

司徒俊良
2023-12-01

orika 映射非空字段

这篇文章着眼于使用Orika将JAXB对象映射到业务域对象。 本月初, 使用基于反射的Dozer讨论 了相同的映射用例 。 在本文中,我假设需要映射相同的示例类,但是它们将使用Orika而不是Dozer进行映射

Dozer和Orika旨在解决相同类型的问题:两个“数据”对象的自动映射,这些对象不共享公共继承,但表示相同的数据字段。 推土机使用反射来完成此操作,而Orika使用反射和字节码操作来完成此操作。 Orika的口号是“更简单,更轻便,更快的Java bean映射”。

Orika拥有版本2Apache许可证,可以从https://github.com/orika-mapper/orika/archive/master.zip (源)或http://search.maven.org/#search下载。 | ga | 1 | orika (二进制)。 Orika对Javassist (用于字节码操作), SLF4Jparanamer (用于在运行时访问方法/构造函数参数名称)具有依赖性 。 这三个依赖项中的两个(JavaAssist和paranamer而不是SLF4J)捆绑在orika-core-1.4.4-deps-included.jar 。 如果依赖项已经可用,则可以使用更薄的orika-core-1.4.4.jar 。 就像这些JAR的名称所暗示的那样,在本文中,我使用Orika 1.4.4作为示例。

在我的“ 推土机:将JAXB对象映射到业务/域对象”一文中 ,我讨论了通常不希望将JAXB生成的类的实例用作业务或域对象的原因。 然后,我展示了JAXB生成的类和自定义数据类之间的“传统”映射方式,以便可以在业务域数据对象中的整个应用程序中传递数据。 在本文中,我将使用相同的方法,但是使用Orika进行映射,而不是执行自定义映射或使用Dozer进行映射。 为方便起见,我在此处列出了JAXB生成的类com.blogspot.marxsoftware.AddressTypecom.blogspot.marxsoftware.PersonType的成本清单,以及重命名的自定义数据类dustin.examples.orikademo.Addressdustin.examples.orikademo.Person

JAXB生成的AddressType.java

//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2013.12.03 at 11:44:32 PM MST 
//

package com.blogspot.marxsoftware;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;

/**
 * <p>Java class for AddressType complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * <complexType name="AddressType">
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <attribute name="streetAddress1" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
 *       <attribute name="streetAddress2" type="{http://www.w3.org/2001/XMLSchema}string" />
 *       <attribute name="city" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
 *       <attribute name="state" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
 *       <attribute name="zipcode" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
 *     </restriction>
 *   </complexContent>
 * </complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "AddressType")
public class AddressType {

    @XmlAttribute(name = "streetAddress1", required = true)
    protected String streetAddress1;
    @XmlAttribute(name = "streetAddress2")
    protected String streetAddress2;
    @XmlAttribute(name = "city", required = true)
    protected String city;
    @XmlAttribute(name = "state", required = true)
    protected String state;
    @XmlAttribute(name = "zipcode", required = true)
    protected String zipcode;

    /**
     * Gets the value of the streetAddress1 property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getStreetAddress1() {
        return streetAddress1;
    }

    /**
     * Sets the value of the streetAddress1 property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setStreetAddress1(String value) {
        this.streetAddress1 = value;
    }

    /**
     * Gets the value of the streetAddress2 property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getStreetAddress2() {
        return streetAddress2;
    }

    /**
     * Sets the value of the streetAddress2 property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setStreetAddress2(String value) {
        this.streetAddress2 = value;
    }

    /**
     * Gets the value of the city property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getCity() {
        return city;
    }

    /**
     * Sets the value of the city property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setCity(String value) {
        this.city = value;
    }

    /**
     * Gets the value of the state property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getState() {
        return state;
    }

    /**
     * Sets the value of the state property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setState(String value) {
        this.state = value;
    }

    /**
     * Gets the value of the zipcode property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getZipcode() {
        return zipcode;
    }

    /**
     * Sets the value of the zipcode property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setZipcode(String value) {
        this.zipcode = value;
    }

}

JAXB生成的PersonType.java

//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2 
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2013.12.03 at 11:44:32 PM MST 
//

package com.blogspot.marxsoftware;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

/**
 * <p>Java class for PersonType complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * <complexType name="PersonType">
 *   <complexContent>
 *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       <sequence>
 *         <element name="MailingAddress" type="{http://marxsoftware.blogspot.com/}AddressType"/>
 *         <element name="ResidentialAddress" type="{http://marxsoftware.blogspot.com/}AddressType" minOccurs="0"/>
 *       </sequence>
 *       <attribute name="firstName" type="{http://www.w3.org/2001/XMLSchema}string" />
 *       <attribute name="lastName" type="{http://www.w3.org/2001/XMLSchema}string" />
 *     </restriction>
 *   </complexContent>
 * </complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PersonType", propOrder = {
    "mailingAddress",
    "residentialAddress"
})
public class PersonType {

    @XmlElement(name = "MailingAddress", required = true)
    protected AddressType mailingAddress;
    @XmlElement(name = "ResidentialAddress")
    protected AddressType residentialAddress;
    @XmlAttribute(name = "firstName")
    protected String firstName;
    @XmlAttribute(name = "lastName")
    protected String lastName;

    /**
     * Gets the value of the mailingAddress property.
     * 
     * @return
     *     possible object is
     *     {@link AddressType }
     *     
     */
    public AddressType getMailingAddress() {
        return mailingAddress;
    }

    /**
     * Sets the value of the mailingAddress property.
     * 
     * @param value
     *     allowed object is
     *     {@link AddressType }
     *     
     */
    public void setMailingAddress(AddressType value) {
        this.mailingAddress = value;
    }

    /**
     * Gets the value of the residentialAddress property.
     * 
     * @return
     *     possible object is
     *     {@link AddressType }
     *     
     */
    public AddressType getResidentialAddress() {
        return residentialAddress;
    }

    /**
     * Sets the value of the residentialAddress property.
     * 
     * @param value
     *     allowed object is
     *     {@link AddressType }
     *     
     */
    public void setResidentialAddress(AddressType value) {
        this.residentialAddress = value;
    }

    /**
     * Gets the value of the firstName property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getFirstName() {
        return firstName;
    }

    /**
     * Sets the value of the firstName property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setFirstName(String value) {
        this.firstName = value;
    }

    /**
     * Gets the value of the lastName property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getLastName() {
        return lastName;
    }

    /**
     * Sets the value of the lastName property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setLastName(String value) {
        this.lastName = value;
    }

}

域/业务类Address.java

package dustin.examples.orikademo;

import java.util.Objects;

/**
 * Address class.
 * 
 * @author Dustin
 */
public class Address
{
   private String streetAddress1;
   private String streetAddress2;
   private String municipality;
   private String state;
   private String zipCode;

   public Address() {}

   public Address(
      final String newStreetAddress1,
      final String newStreetAddress2,
      final String newMunicipality,
      final String newState,
      final String newZipCode)
   {
      this.streetAddress1 = newStreetAddress1;
      this.streetAddress2 = newStreetAddress2;
      this.municipality = newMunicipality;
      this.state = newState;
      this.zipCode = newZipCode;
   }

   public String getStreetAddress1()
   {
      return this.streetAddress1;
   }

   public void setStreetAddress1(String streetAddress1)
   {
      this.streetAddress1 = streetAddress1;
   }

   public String getStreetAddress2()
   {
      return this.streetAddress2;
   }

   public void setStreetAddress2(String streetAddress2)
   {
      this.streetAddress2 = streetAddress2;
   }

   public String getMunicipality()
   {
      return this.municipality;
   }

   public void setMunicipality(String municipality)
   {
      this.municipality = municipality;
   }

   public String getState() {
      return this.state;
   }

   public void setState(String state)
   {
      this.state = state;
   }

   public String getZipCode() 
   {
      return this.zipCode;
   }

   public void setZipCode(String zipCode)
   {
      this.zipCode = zipCode;
   }

   @Override
   public int hashCode()
   {
      return Objects.hash(
         this.streetAddress1, this.streetAddress2, this.municipality,
         this.state, this.zipCode);
   }

   @Override
   public boolean equals(Object obj)
   {
      if (obj == null) {
         return false;
      }
      if (getClass() != obj.getClass()) {
         return false;
      }
      final Address other = (Address) obj;
      if (!Objects.equals(this.streetAddress1, other.streetAddress1))
      {
         return false;
      }
      if (!Objects.equals(this.streetAddress2, other.streetAddress2))
      {
         return false;
      }
      if (!Objects.equals(this.municipality, other.municipality))
      {
         return false;
      }
      if (!Objects.equals(this.state, other.state))
      {
         return false;
      }
      if (!Objects.equals(this.zipCode, other.zipCode))
      {
         return false;
      }
      return true;
   }

   @Override
   public String toString()
   {
      return "Address{" + "streetAddress1=" + streetAddress1 + ", streetAddress2="
         + streetAddress2 + ", municipality=" + municipality + ", state=" + state
         + ", zipCode=" + zipCode + '}';
   }

}

域/业务类Person.java

package dustin.examples.orikademo;

import java.util.Objects;

/**
 * Person class.
 * 
 * @author Dustin
 */
public class Person
{
   private String lastName;
   private String firstName;
   private Address mailingAddress;
   private Address residentialAddress;

   public Person() {}

   public Person(
      final String newLastName,
      final String newFirstName,
      final Address newResidentialAddress,
      final Address newMailingAddress)
   {
      this.lastName = newLastName;
      this.firstName = newFirstName;
      this.residentialAddress = newResidentialAddress;
      this.mailingAddress = newMailingAddress;
   }

   public String getLastName()
   {
      return this.lastName;
   }

   public void setLastName(String lastName) {
      this.lastName = lastName;
   }

   public String getFirstName()
   {
      return this.firstName;
   }

   public void setFirstName(String firstName)
   {
      this.firstName = firstName;
   }

   public Address getMailingAddress()
   {
      return this.mailingAddress;
   }

   public void setMailingAddress(Address mailingAddress)
   {
      this.mailingAddress = mailingAddress;
   }

   public Address getResidentialAddress()
   {
      return this.residentialAddress;
   }

   public void setResidentialAddress(Address residentialAddress)
   {
      this.residentialAddress = residentialAddress;
   }

   @Override
   public int hashCode()
   {
      int hash = 3;
      hash = 19 * hash + Objects.hashCode(this.lastName);
      hash = 19 * hash + Objects.hashCode(this.firstName);
      hash = 19 * hash + Objects.hashCode(this.mailingAddress);
      hash = 19 * hash + Objects.hashCode(this.residentialAddress);
      return hash;
   }

   @Override
   public boolean equals(Object obj)
   {
      if (obj == null)
      {
         return false;
      }
      if (getClass() != obj.getClass())
      {
         return false;
      }
      final Person other = (Person) obj;
      if (!Objects.equals(this.lastName, other.lastName))
      {
         return false;
      }
      if (!Objects.equals(this.firstName, other.firstName))
      {
         return false;
      }
      if (!Objects.equals(this.mailingAddress, other.mailingAddress))
      {
         return false;
      }
      if (!Objects.equals(this.residentialAddress, other.residentialAddress))
      {
         return false;
      }
      return true;
   }

   @Override
   public String toString() {
      return  "Person{" + "lastName=" + lastName + ", firstName=" + firstName
            + ", mailingAddress=" + mailingAddress + ", residentialAddress="
            + residentialAddress + '}';
   }

}

与Dozer一样,要映射的类需要具有无参数的构造函数以及“ set”和“ get”方法以支持双向转换,而无需任何特殊的附加配置。 另外,与Dozer一样,Orika会自动映射同名字段,并易于配置异常的映射(名称不匹配的字段)。 下一个代码清单(针对我称为OrikaPersonConverter的类)演示了OrikaPersonConverter MapperFactory的实例化和配置,以默认情况下映射大多数字段,并通过显式映射来映射名称彼此不同的字段 (“市政”和“城市”)组态。 一旦配置MapperFactory ,就可以轻松地从一个对象复制到另一个对象,并且两个方向都在copyPersonTypeFromPersoncopyPersonFromPersonType方法中进行了描述。

OrikaPersonConverter

package dustin.examples.orikademo;

import com.blogspot.marxsoftware.AddressType;
import com.blogspot.marxsoftware.PersonType;
import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;

/**
 * Convert between instances of {@link com.blogspot.marxsoftware.PersonType}
 * and {@link dustin.examples.orikademo.Person}.
 * 
 * @author Dustin
 */
public class OrikaPersonConverter
{
   /** Orika Mapper Facade. */
   private final static MapperFacade mapper;

   static
   {
      final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
      mapperFactory.classMap(Address.class, AddressType.class)
                   .field("municipality", "city")
                   .byDefault()
                   .register();
      mapper = mapperFactory.getMapperFacade();
   }

   /** No-arguments constructor. */
   public OrikaPersonConverter() {}

   /**
    * Provide an instance of {@link com.blogspot.marxsoftware.PersonType}
    * that corresponds with provided {@link dustin.examples.orikademo.Person} as
    * mapped by Dozer Mapper.
    * 
    * @param person Instance of {@link dustin.examples.orikademo.Person} from which
    *    {@link com.blogspot.marxsoftware.PersonType} will be extracted.
    * @return Instance of {@link com.blogspot.marxsoftware.PersonType} that
    *    is based on provided {@link dustin.examples.orikademo.Person} instance.
    */
   public PersonType copyPersonTypeFromPerson(final Person person)
   {
      PersonType personType = mapper.map(person, PersonType.class);
      return personType;
   }

   /**
    * Provide an instance of {@link dustin.examples.orikademo.Person} that corresponds
    * with the provided {@link com.blogspot.marxsoftware.PersonType} as 
    * mapped by Dozer Mapper.
    * 
    * @param personType Instance of {@link com.blogspot.marxsoftware.PersonType}
    *    from which {@link dustin.examples.orikademo.Person} will be extracted.
    * @return Instance of {@link dustin.examples.orikademo.Person} that is based on the
    *    provided {@link com.blogspot.marxsoftware.PersonType}.
    */
   public Person copyPersonFromPersonType(final PersonType personType)
   {
      Person person = mapper.map(personType, Person.class);
      return person;
   }
}

与Dozer的情况一样,两个类之间的映射是双向的,因此只需进行一次映射,并将应用于从一个对象到另一个对象的复制。

结论

像推土机一样,Orika提供的自定义性和灵活性比本文中演示的要好得多。 但是,对于相对简单的映射(在使用JAXB生成的对象的应用程序中很常见),Orika非常易于使用。 《 Orika用户指南》是了解更多有关Orika的好资源。


翻译自: https://www.javacodegeeks.com/2013/12/orika-mapping-jaxb-objects-to-businessdomain-objects.html

orika 映射非空字段

 类似资料: