开发中,会出现对象之间的相互转化,或者是根据某一对象转化成另一个对象。
一般如果手动get和set还是比较费时费力的,此时可以使用Orika的MapperFacade。
别的方式还有dozer JMapper mapStruck等方式。
效率:因为Orika的设计思路是预先通过javaassist把JavaBean之间的映射关系一次性生成目标拷贝方法代码。 这样就可以避免在Bean 映射环节一次次的读取映射规则。 从而实现效率上的提高。
这里以Springboot集成MapperFactory为实例。
maven包引入
官网:http://orika-mapper.github.io/orika-docs/intro.html
<dependency>
<groupId>ma.glasnost.orika</groupId>
<artifactId>orika-core</artifactId>
</dependency>
基础概念
MapperFactory
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
MapperFactory用于注册字段映射,配置转换器,自定义映射器等,而我们关注的主要是字段映射这个特性,在下面的小节中会介绍。
MapperFacade
MapperFacade mapper = mapperFactory.getMapperFacade();
PersonSource source = new PersonSource();
PersonDest destination = mapper.map(source, PersonDest.class);
MapperFacade和spring,apache中的BeanUtils具有相同的地位,负责对象间的映射,也是实际使用中,我们使用的最多的类。
springBoot中的使用
编写容器注入的类
package com.kingboy.springboot.config;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MapperFacotoryAutoWire {
@Bean
public MapperFactory getFactory(){
return new DefaultMapperFactory.Builder().build();
}
}
使用
基础dto定义
import java.time.LocalDateTime;
import java.util.Date;
public class Person {
public Person() {
}
public Person(String name, Integer age, Date dateTime) {
this.name = name;
this.age = age;
this.dateTime = dateTime;
}
private String name;
private Integer age;
private Date dateTime;
public String getName() {
return name;
}
public Person setName(String name) {
this.name = name;
return this;
}
public Integer getAge() {
return age;
}
public Person setAge(Integer age) {
this.age = age;
return this;
}
public Date getDateTime() {
return dateTime;
}
public Person setDateTime(Date dateTime) {
this.dateTime = dateTime;
return this;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", dateTime=" + dateTime +
'}';
}
}
import java.time.LocalDateTime;
import java.util.Date;
public class Student {
private String name;
private String grade;
private Integer age;
private Date birth;
public Date getBirth() {
return birth;
}
public Student setBirth(Date birth) {
this.birth = birth;
return this;
}
public String getName() {
return name;
}
public Student setName(String name) {
this.name = name;
return this;
}
public String getGrade() {
return grade;
}
public Student setGrade(String grade) {
this.grade = grade;
return this;
}
public Integer getAge() {
return age;
}
public Student setAge(Integer age) {
this.age = age;
return this;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", grade='" + grade + '\'' +
", age=" + age +
", birth=" + birth +
'}';
}
}
映射代码
import com.kingboy.springboot.KingBoyApplication;
import com.kingboy.springboot.domain.Person;
import com.kingboy.springboot.domain.Student;
import com.kingboy.springboot.repository.CityRepository;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.metadata.ClassMapBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@SpringBootTest(classes = KingBoyApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
public class MapperFactoryTest {
@Autowired
private MapperFactory mapperFactory;
/**
* 将一个已经存在的类的属性映射到另外一个类上(可以不存在),直接返回该类,注意必须要有默认构造方法,不然报错
*/
@Test
public void copyBeanToBean(){
Person person = new Person("king", 123, new Date());
mapperFactory.classMap(Person.class, Student.class)
.field("dateTime","birth")//不一样的字段映射
.byDefault()//剩余的字段映射
.register();
//如果所有字段一样,则不用写mapperFactory.classMap()方法;
Student student = mapperFactory.getMapperFacade().map(person, Student.class);
System.out.println(student);
//Student{name='king', grade='null', age=123, birth=Thu Apr 13 19:04:43 CST 2017}
}
/**
* 将一个List映射到另一个List
*/
@Test
public void copyListToList(){
List<Person> personList = getPersonList();
//手动配置不一样的属性转换
mapperFactory.classMap(Person.class, Student.class)
.field("dateTime","birth")//不一样的字段映射
.byDefault()//剩余的字段映射
.register();
//转换List
List<Student> students = mapperFactory.getMapperFacade().mapAsList(personList, Student.class);
students.forEach(student -> {
System.out.println(student);
});
/**
* Student{name='king1', grade='null', age=1, birth=Thu Apr 13 19:10:39 CST 2017}
*Student{name='king2', grade='null', age=2, birth=Thu Apr 13 19:10:39 CST 2017}
*Student{name='king3', grade='null', age=3, birth=Thu Apr 13 19:10:39 CST 2017}
*Student{name='king4', grade='null', age=4, birth=Thu Apr 13 19:10:39 CST 2017}
*Student{name='king5', grade='null', age=5, birth=Thu Apr 13 19:10:39 CST 2017}
*/
}
public List<Person> getPersonList(){
List<Person> list = new ArrayList<>(5);
Person person1 = new Person("king1", 1, new Date());
Person person2 = new Person("king2", 2, new Date());
Person person3 = new Person("king3", 3, new Date());
Person person4 = new Person("king4", 4, new Date());
Person person5 = new Person("king5", 5, new Date());
list.add(person1);
list.add(person2);
list.add(person3);
list.add(person4);
list.add(person5);
return list;
}
}
参考:
https://blog.csdn.net/kingboyworld/article/details/70161172
如果两个dto属性名称不同怎么办?
https://blog.csdn.net/liboyang71/article/details/75072995
https://cloud.tencent.com/developer/article/1110666