ModelMapper
1. 簡單使用
(1) 引入maven
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>1.1.0</version>
</dependency>
(2) 簡單操作
//創建 ModelMapper 類
ModelMapper modelMapper = new ModelMapper();
// S 實體相同字段映射到 T 實體
T map = modelMapper.map(S s, T.class);
//集合映射
List<T> map = modelMapper.map(List<S> s, new TypeToken<List<T>>() {}.getType());
2. 組件與配置
(1) modelMapperAPI
//未有對象映射
BEntity bEntity = modelMapper.map(AEntity aEntity,BEntity.class);
//已有對象映射
modelMapper.map(AEntity aEntity,BEntity bEntity);
//使用泛型
Type type = new TypeToken<List<T>>() {}.getType();//定義泛型,用於映射list
modelMapper.map(AEntity aEntity,Type type);
//驗證映射,目標對象有字段沒有映射報錯
modelMapper.validate();
//添加轉換器
modelMapper.addConverter(Converter<S, D> converter);
//添加映射規則
modelMapper.addMappings(PropertyMap<S, D> propertyMap);
//獲取配置類,可查看和修改
Configuration configuration = modelMapper.getConfiguration();
//創建映射
TypeMap< AEntity,BEntity> typeMap =modelMapper.createTypeMap(AEntity.class,BEntity.class);
(2) 類型映射
//字段映射
//添加映射字段
typeMap.addMapping(BEntity::getAField,CEntity::setHField);
//添加映射字段
typeMap.addMappings(mapper -> mapper.map(BEntity::getAField,CEntity::setGField));
//忽略映射字段
typeMap.addMappings(mapper -> mapper.skip(CEntity::setEField));
//添加轉換器映射
typeMap.addMappings(mapper -> mapper.using(Converter<String, String> converter).map(BEntity::getAField,CEntity::setFField))
//添加提供者映射
typeMap.addMappings(mapper ->mapper.with(Provider<String>) context).map(BEntity::getAField,CEntity::setFField) )
//添加過濾條件映射
typeMap.addMappings(mapper ->mapper.when(Condition<String,String>) condition).map(BEntity::getAField,CEntity::setFField));
//深度映射 對象->對象字段->字段 ---> 對象 -> 字段
typeMap.addMappings(mapper -> mapper.map(src -> src.getCEntity().getEField(), BEntity::setAField));
//深度映射 對象->對象字段->字段 ---> 對象->對象字段 -> 字段
typeMap.addMappings(mapper -> mapper.<String>map(src -> src.getCEntity().getFField(), (dest, v) -> dest.getCEntity().setHField(v)));
//設置提供者
//字段提供者,爲目標字段提供值,
typeMap.setPropertyProvider(Provider<D> provider)
//對象提供者,在有沒目標對象映射時,可自定義提供目標對象
typeMap.setProvider(Provider<D> provider)
//設置映射條件
//對象條件
typeMap.setCondition(Condition<?, ?> condition);
//字段條件,當對象條件不通過時,不會執行字段條件
typeMap.setPropertyCondition(Condition<?, ?> condition);
//設置轉換器
//對象轉換器,可用來 處理映射 ,返回目標對象,有該轉換器,其他不生效
typeMap.setConverter(Converter<S, D> converter);
//沒有setConverter時執行,在進行字段映射前執行
typeMap.setPreConverter(Converter<S, D> converter);
//沒有setConverter時執行,在進行字段映射時執行
typeMap.setPropertyConverter(Converter<S, D> converter);
//沒有setConverter時執行,在進行字段映射後執行
typeMap.setPostConverter(Converter<S, D> converter);
(3) 配置
//控制類配置
configuration .setFullTypeMatchingRequired(true);//需要完整類型匹配
configuration .setFieldMatchingEnabled(true);//字段匹配已啓用
configuration .setSkipNullEnabled(true);//跳過空值已啓用
configuration .setAmbiguityIgnored(true);//忽略歧義
configuration .setImplicitMappingEnabled(true);//隱式映射已啓用
//訪問級別配置
configuration .setMethodAccessLevel(Configuration.AccessLevel.PACKAGE_PRIVATE);//方法訪問級別
modelMapper.getConfiguration().setFieldAccessLevel(Configuration.AccessLevel.PRIVATE);//字段訪問級別
//命名方式
configuration .setSourceNameTokenizer(NameTokenizers.CAMEL_CASE);//來源名稱命名方式
configuration .setDestinationNameTokenizer(NameTokenizers.CAMEL_CASE);//目標名稱命名方式
//名稱轉換方式
configuration .setSourceNameTransformer(NameTransformers.JAVABEANS_MUTATOR);//來源名稱轉換方式
configuration .setDestinationNameTransformer(NameTransformers.JAVABEANS_MUTATOR);//目標名稱轉換方式
//命名約定
configuration .setDestinationNamingConvention(NamingConventions.JAVABEANS_ACCESSOR);//目標地命名約定
configuration .setSourceNamingConvention(NamingConventions.JAVABEANS_ACCESSOR);//來源命名約定
//匹配策略
configuration .setMatchingStrategy(MatchingStrategies.LOOSE);
//設置提供者
configuration .setProvider((Provider<String>) provider->{
return "";
});
//設置條件
configuration .setPropertyCondition((Condition<String,String>) condition ->{
return true;
});
可以配置常量:
命名約定( NamingConventions ) |
NamingConventions.NONE | 表示沒有命名約定,該約定適用於所有屬性名稱 |
NamingConventions.JAVABEANS_ACCESSOR | 根據JavaBeans約定查找合格的訪問者 | |
NamingConventions.JAVABEANS_MUTATOR | 根據JavaBeans約定查找合格的mutator | |
名稱轉化器(NameTransformer) | NameTransformers.JAVABEANS_ACCESSOR | 根據JavaBeans約定轉換訪問者名稱 |
NameTransformers.JAVABEANS_MUTATOR | 根據JavaBeans set方法轉換變量名稱 | |
命名方式 (NameTokenizers) |
NameTokenizers.CAMEL_CASE | 根據[ 駝峯]對屬性和類名進行標記 |
NameTokenizers.UNDERSCORE | 用[下劃線標記]屬性和類的名稱 | |
匹配策略(MatchingStrategies) | MatchingStrategies.STANDARD | 智能匹配源和目標屬性 |
MatchingStrategies.LOOSE | 鬆散匹配源屬性和目標屬性 | |
MatchingStrategies.STRICT | 嚴格匹配源和目標屬性 | |
訪問級別(AccessLevel) | Configuration.AccessLevel.PUBLIC | 公開,公共的 |
Configuration.AccessLevel.PROTECTED | 同一包中 | |
Configuration.AccessLevel.PACKAGE_PRIVATE | 同一子包中 | |
Configuration.AccessLevel.PRIVATE | 同一類中 |
(3) 映射器
添加字段映射,及各字段映射處理
//自定義映射
PropertyMap<AEntity,CEntity> propertyMap = new PropertyMap<AEntity, CEntity>() {
@Override
protected void configure() {
/**使用自定義轉換規則*/
map(source.getAField(), destination.getBField());//主動替換屬性
map().setAField(source.getBField());/BField字段賦值給AField
using(toUppercase).map(source.getAField(),destination.getBField());//使用自定義轉換規則
with(personProvider).map(source.getBField(),destination.getBField());//使用自定義屬性提供覆蓋
skip(destination.getAField());//過濾指定屬性,非對象
skip().setDtoOnlyProperty(null);//過濾指定屬性,對象
when(condition).map().setAField("value");//條件過濾屬性,條件符合賦值value
}
};
(4) 轉換器
可進行字段數據處理,類型轉換等操作.
//定義轉換器
Converter<S, D> toUppercase = new AbstractConverter<S, D>() {
@Override
protected Dconvert(S source) {
//處理原對象,返回目標對象
return source;
}
};
//lambda表達式方式
Converter<String, String> converter = ctx -> ctx.getSource() == null ? null : ctx.getSource();
(5) 提供者
可用於設置映射條件,條件滿足進行條件映射.可通過 Configuration 和 TypeMap 配置,[typeMap.setProvider]可設置一個目標對象;[typeMap.setPropertyProvider] 可爲 源對象 字段 提供值;Configuration 可同時設置對象與字段屬性,處理需判斷類型
//轉換內容提供者
Provider<String> personProvider = new AbstractProvider<String>() {
@Override
public String get() {
//返回要添加的內容
return "自定義提供者";
}
};
//lambda表達式方式
Provider<String> provider = req -> new String();
(6) 條件
可用於設置映射條件,條件滿足進行條件映射.可通過 Configuration 和 TypeMap 配置
//創建自定義條件轉換 注:以下Condition 可添加兩泛值Condition<?,?>
Condition condition =new Condition() {
@Override
public boolean applies(MappingContext mappingContext) {
//處理字段,返回false不映射
return false;
}
};
//lambda表達式方式
Condition notNull = ctx -> ctx.getSource() != null;
//內置條件
//原對象字段值爲空不映射
Condition notNull1 = Conditions.isNotNull();
//原對象字段值爲空映射
Condition isNull = Conditions.isNull();
//判斷原對象字段類型,符合映射
Condition isType = Conditions.isType(String.class);
//條件取交集
Condition and = Conditions.and(Condition c1,Condition c2);
//條件取反集
Condition not = Conditions.not(Condition c);
//條件取並集
Condition or = Conditions.or(Condition c1,Condition c2);
MapStruct
1. 簡單使用
(1) 引入maven
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.2.0.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.2.0.Final</version>
</dependency>
(2) 定義接口
package com.example.demo.mapstruct;
import com.example.demo.pojo.ABean;
import com.example.demo.pojo.BBean;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
@Mapper
public interface Converter {
Converter INSTANCE = Mappers.getMapper(Converter.class);
@Mappings({
@Mapping(source = "aField", target = "bField"),
})
BBean domain2dto(ABean aBean);
//默認處理方法
default BBean domain2dto1(ABean aBean) {
//hand-written mapping logic
}
}
(3) 簡單操作
BBean bBean = PersonConverter.INSTANCE.domain2dto(ABean aBean);
2. 常用註解
@Mapper 只有在接口加上這個註解, MapStruct 纔會去實現該接口
componentModel屬性,主要是指定實現類的類型,一般用到兩個
default:默認,可以通過Mappers.getMapper(Class)方式獲取實例對象
spring:在接口的實現類上自動添加註解@Component,可通過@Autowired方式注入
@Mapping:屬性映射,若源對象屬性與目標對象名字一致,會自動映射對應屬性
source:源屬性
target:目標屬性
dateFormat:String到Date日期之間相互轉換,通過SimpleDateFormat,該值爲SimpleDateFormat的日期格式
ignore:忽略這個字段
@Mappings:配置多個@Mapping
@MappingTarget用於更新已有對象
@InheritConfiguration用於繼承配置
4. 應用詳解
(1) 添加默認方法
default Bean1 defaultConvert(Bean2 bean2) {
//進行映射處理及其他處理
return bean1;
}
(2) 使用abstract class來代替接口
package com.example.demo.mapstruct;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
@Mapper
public abstract class Converter {
Converter INSTANCE = Mappers.getMapper(Converter.class);
@Mappings({
@Mapping(source = "aField", target = "bField"),
})
public abstract BBean domain2dto(ABean aBean);
}
(3) 可以使用多個參數
@Mappings({
@Mapping(source = "bean1.field1", target = "field1"),
@Mapping(source = "bean2.field1", target = "field2")
})
Bean3 toUserRoleDto(Bean1 bean1, Bean2 bean2);
(4) 直接使用參數作爲屬性值
@Mappings({
@Mapping(source = "field", target = "field")
})
Bean useParameter(String field);
(5) 更新對象屬性
@Mappings({
@Mapping(source = "field", target = "field")
})
void update(Bean2 bean2, @MappingTarget Bean1 bean1);//@MappingTarget 指定目標對象
(6) 使用Spring依賴注入
//添加 componentModel 屬性
@Mapper(componentModel = "spring")
public interface ConverterMapper {}
// 自動注入
@Autowired
private ConverterMapper mapper;
(7) 自定義類型轉換
//@Mapper註解加uses屬性
@Mapper( uses = { MyConversion.class})
//自定義轉換器,field爲對應的轉換的字段 MyConversion|conversion自定義
public class MyConversion{
public String conversion(String field) {
return field;
}
}