Orika對象復制教程(完美筆記)


 一、Orika背景介紹
   

  Orika是java Bean映射框架,可以實現從一個對象遞歸拷貝數據至另一個對象。在開發多層應用程序中非常有用。在這些層之間交換數據時,通常為了適應不同API需要轉換一個實例至另一個實例。

  有很多方法可以實現:硬代碼拷貝或Dozer實現bean映射等。總之,需要簡化不同層對象之間映射過程。

    Orika使用字節碼生成器創建開銷最小的快速映射,比其他基於反射方式實現(如,Dozer)更快。之前使用Bean Copy 性能非常慢,發現在這個領域業界還是有很多新秀的。 Orika 應該就算一個比較好的吧。


 二、優勢


1. 性能
  大概是Dozer的8-10 倍, 這個上面的已經做了描述

2. 內存消耗
  大概是Dozer內存消耗的一半多點。 為什么做到這點的還沒想清楚, 估計是因為運行期不需要維護復雜的Mapping 關系。 不需要大量的Mapping 關系查找以及需要的對這些查找優化所消耗的空間。

3. 簡單
  Orika的代碼短小精悍, 而且可讀性非常強, Dozer如果要加減一個功能, 不才完全沒有信心, Orika 我還是可以偶爾在Orika里面打幾個醬油的。


三、基礎使用

  • Maven項目依賴包:POM文件直接依賴進去即可。

 

<dependency>
    <groupId>ma.glasnost.orika</groupId>
    <artifactId>orika-core</artifactId>
    <version>1.4.6</version>
</dependency>

 

  • 創建兩個Bean對象,用於復制使用。

  UserVo對象

 

@Data //Set GET方法
@Accessors(chain = true)
public class UserVo {
private String id;
private String name;
}

 

  User對象

@Data
@Accessors(chain = true)
public class User {
private String id;
private String name;
}

 

  • 使用場景(如果對象中屬性太多,普通邏輯處理代碼太多)
  1. A對象復制到B對象(對象復制)
//業務場景,將A對象復制B對象中
//1.普通邏輯處理
User A = new User().setId("123").setName("1231");
UserVo B = new UserVo().setId(A.getId()).setName(A.getName());
System.out.println("普通方式將A對象復制B對象中:"+B);

//使用orika復制工具將A復制到B對象中
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
UserVo map = mapperFactory.getMapperFacade().map(A, UserVo.class);
System.out.println("orika復制對象:"+map);

 

  • 由上得出控制台輸出如下
普通方式將A對象復制B對象中:UserVo(id=123, name=1231) orika復制對象:UserVo(id=123, name=1231)

 


  2.A集合復制到B集合(集合復制)

//1.普通邏輯處
//A對象
List<User> A = Arrays.asList(new User().setId("123").setName("張三"));
//B對象
List<UserVo> B = new ArrayList<>();
//將A集合數據復制到B集合中
A.forEach(x->{
B.add( new UserVo().setId(x.getId()).setName(x.getName()));
});
System.out.println("將A集合中數據set到B集合中數據打印");

//使用orika復制工具將A集合復制到B集合中
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
List<UserVo> userVo = mapperFactory.getMapperFacade().mapAsList
mapperFactory.getMapperFacade().mapAsList(A, UserVo.class);
System.out.println("orika直接復制對象集合打印結果:"+userVo);

 

 

  • 由上得出控制台輸出如下:
`將A集合中數據set到B集合中數據打印:[UserVo(id=123, name=張三)]`

`orika直接復制對象集合打印結果:[UserVo(id=123, name=張三)]`

 

  • 到此為止您已經算入門了,以上是Orika的基礎使用,由此發現如果對象中屬性如果20個,那么用普通的邏輯處理需要20個set過去,如果用Orika兩行代碼搞定。話不多說關鍵步驟總結一波(關鍵必須牢記):
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.getMapperFacade().map(操作對象)
mapperFactory.getMapperFacade().mapAsList(操作集合對象)

 


四、高級使用方法

  •  創建兩個Bean對象,用於復制使用。

   UserVo對象

@Data //Set GET方法
@Accessors(chain = true)
public class UserVo {
private String id;
private String userName;
private int ageOne;
}


  User對象

@Data
@Accessors(chain = true)
public class User {
private String id;
private String name;
private int age;
}

 

 

  • 使用場景(對象A與對象B中屬性不一致時,如果對象中屬性太多,普通邏輯處理代碼太多)

  1.A對象復制到B對象,對象中屬性不一樣時

//業務場景,將A對象復制B對象中,A對象中的字段與B對象中的字段不一致
//1.普通邏輯處理
User A = new User().setId("123").setName("張三").setAge(20);
UserVo B = new UserVo().setId(A.getId()).setUserName(A.getName()).setAgeOne(A.getAge());
System.out.println("普通方式將A對象處理B對象中:"+B);.

//使用orika復制工具將A復制到B對象中
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(User.class, UserVo.class)
.field("name", "userName")
.field("age", "ageOne")
.byDefault().register();
UserVo userVo = mapperFactory.getMapperFacade().map(A, UserVo.class);
System.out.println("orika復制對象:"+userVo);
  • 由上得出控制台輸出如下:
`普通方式將A對象處理B對象中:UserVo(id=123, userName=張三, ageOne=20)`

`orika復制對象:UserVo(id=123, userName=張三, ageOne=20)`

 


  2.A集合對象復制到B集合對象,對象中屬性不一樣時

//1.普通邏輯處里A對象中與B對象字段不一致處理
//A對象
List<User> A = Arrays.asList(new User().setId("123").setName("張三").setAge(20));
//B對象
List<UserVo> B = new ArrayList<>();
//將A集合數據復制到B集合中
A.forEach(x->{
B.add(new UserVo().setId(x.getId()).setUserName(x.getName()).setAgeOne(x.getAge()));
});
System.out.println("將A集合中數據set到B集合中數據打印"+B);

//使用orika復制工具將A集合復制到B集合中
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(User.class, UserVo.class)
.field("name", "userName")
.field("age", "ageOne")
.byDefault().register();
List<UserVo> userVos = mapperFactory.getMapperFacade().mapAsList(A, UserVo.class);
System.out.println("orika復制對象:"+userVos);

 

  • 由上得出控制台輸出如下:
`將A集合中數據set到B集合中數據打印[UserVo(id=123, userName=張三, ageOne=20)]`

`orika復制對象:[UserVo(id=123, userName=張三, ageOne=20)]`

 

 

  • 話不多說關鍵步驟總結一波(關鍵必須牢記):
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(User.class, UserVo.class)
.field("name", "userName")
.field("age", "ageOne")
.byDefault().register();
//集合復制--使用mapAsList
List<UserVo> userVos = mapperFactory.getMapperFacade().mapAsList(A, UserVo.class);
//對象復制--使用map
UserVo userVos = mapperFactory.getMapperFacade().map(A, UserVo.class);

 


五、總結工具類

/**
* 映射工具類
*/
public enum MapperUtils {

INSTANCE;

/**
* 默認字段工廠
*/
private static final MapperFactory MAPPER_FACTORY = new DefaultMapperFactory.Builder().build();

/**
* 默認字段實例
*/
private static final MapperFacade MAPPER_FACADE = MAPPER_FACTORY.getMapperFacade();

/**
* 默認字段實例集合
*/
private static Map<String, MapperFacade> CACHE_MAPPER_FACADE_MAP = new ConcurrentHashMap<>();

/**
* 映射實體(默認字段)
*
* @param toClass 映射類對象
* @param data 數據(對象)
* @return 映射類對象
*/
public <E, T> E map(Class<E> toClass, T data) {
return MAPPER_FACADE.map(data, toClass);
}

/**
* 映射實體(自定義配置)
*
* @param toClass 映射類對象
* @param data 數據(對象)
* @param configMap 自定義配置
* @return 映射類對象
*/
public <E, T> E map(Class<E> toClass, T data, Map<String, String> configMap) {
MapperFacade mapperFacade = this.getMapperFacade(toClass, data.getClass(), configMap);
return mapperFacade.map(data, toClass);
}

/**
* 映射集合(默認字段)
*
* @param toClass 映射類對象
* @param data 數據(集合)
* @return 映射類對象
*/
public <E, T> List<E> mapAsList(Class<E> toClass, Collection<T> data) {
return MAPPER_FACADE.mapAsList(data, toClass);
}


/**
* 映射集合(自定義配置)
*
* @param toClass 映射類
* @param data 數據(集合)
* @param configMap 自定義配置
* @return 映射類對象
*/
/* public <E, T> List<E> mapAsList(Class<E> toClass, Collection<T> data, Map<String, String> configMap) {
T t = data.stream().findFirst().orElseThrow(() -> new ResourceNotExistException("映射集合,數據集合為空"));
MapperFacade mapperFacade = this.getMapperFacade(toClass, t.getClass(), configMap);
return mapperFacade.mapAsList(data, toClass);
}*/

/**
* 獲取自定義映射
*
* @param toClass 映射類
* @param dataClass 數據映射類
* @param configMap 自定義配置
* @return 映射類對象
*/
private <E, T> MapperFacade getMapperFacade(Class<E> toClass, Class<T> dataClass, Map<String, String> configMap) {
String mapKey = dataClass.getCanonicalName() + "_" + toClass.getCanonicalName();
MapperFacade mapperFacade = CACHE_MAPPER_FACADE_MAP.get(mapKey);
if (Objects.isNull(mapperFacade)) {
MapperFactory factory = new DefaultMapperFactory.Builder().build();
ClassMapBuilder classMapBuilder = factory.classMap(dataClass, toClass);
configMap.forEach(classMapBuilder::field);
classMapBuilder.byDefault().register();
mapperFacade = factory.getMapperFacade();
CACHE_MAPPER_FACADE_MAP.put(mapKey, mapperFacade);
}
return mapperFacade;
}

}

 

 

1.orika底層實現原理:(后續加上)


2.如果有任何不懂的地方可以咨詢我,隨時歡迎互相幫助。


3.以上完整代碼加群(群文件):422167709

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM