我有以下代码将类User
的对象转换为类型为GetUserDto
的DTO:
public GetUserDto convertToDto(User user) {
Converter<User, GetUserDto> converter = context -> {
User source = context.getSource();
GetUserDto target = new GetUserDto();
target.setDescription(source.getDescription());
target.setId(source.getId());
target.setName(source.getName());
target.setImageId(source.getImageId());
return target;
};
modelMapper.createTypeMap(User.class, GetUserDto.class).setConverter(converter);
return modelMapper.map(user, GetUserDto.class);
}
第一次运行正常,但随后对
convertToDto
的调用引发:java.lang.IllegalStateException: A TypeMap already exists for class com.boot.cut_costs.model.User and class com.boot.cut_costs.dto.user.ExtendedGetUserDto
我发现了其他与此相关的帖子,其中有人建议对
TypeMap
进行空检查以检查modelMapper
,如果不是null
,则不要再次创建它。这不是一个好的解决方案,因为您有成千上万次调用此方法,因此会增加不必要的开销。有什么好的解决方案吗?
最佳答案
我发现了其他与此相关的帖子,其中一项建议取消检查
用于ModelMapper的TypeMap,如果不为null,则不要再次创建它。
这不是一个好的解决方案,就好像您有成千上万的呼叫
方法会增加不必要的开销。
如果您查看org.modelmapper.ModelMapper.getTypeMap()
的代码
和org.modelmapper.ModelMapper.createTypeMap()
,您将看到
创建一个开销更大的TypeMap
,就像调用方法来检索TypeMap
一样。
从地图返回对象(如果存在)是直接的:
public <S, D> TypeMap<S, D> getTypeMap(Class<S> sourceType, Class<D> destinationType) {
Assert.notNull(sourceType, "sourceType");
Assert.notNull(destinationType, "destinationType");
return config.typeMapStore.<S, D>get(sourceType, destinationType, null);
}
虽然添加执行更多的事情。
它创建代理类型,执行同步任务,并在创建
TypeMap
实例之前进行一些检查,最后将其放入地图中: private <S, D> TypeMap<S, D> createTypeMapInternal(S source, Class<S> sourceType,
Class<D> destinationType, String typeMapName, Configuration configuration) {
if (source != null)
sourceType = Types.<S>deProxy(source.getClass());
Assert.state(config.typeMapStore.get(sourceType, destinationType, typeMapName) == null,
String.format("A TypeMap already exists for %s and %s", sourceType, destinationType));
return config.typeMapStore.create(source, sourceType, destinationType, typeMapName,
(InheritingConfiguration) configuration, engine);
}
还会调用:
public <S, D> TypeMap<S, D> create(S source, Class<S> sourceType, Class<D> destinationType,
String typeMapName, InheritingConfiguration configuration, MappingEngineImpl engine) {
synchronized (lock) {
TypeMapImpl<S, D> typeMap = new TypeMapImpl<S, D>(sourceType, destinationType, typeMapName,
configuration, engine);
if (configuration.isImplicitMappingEnabled()
&& ImplicitMappingBuilder.isMatchable(typeMap.getSourceType())
&& ImplicitMappingBuilder.isMatchable(typeMap.getDestinationType()))
new ImplicitMappingBuilder<S, D>(source, typeMap, config.typeMapStore,
config.converterStore).build();
typeMaps.put(TypePair.of(sourceType, destinationType, typeMapName), typeMap);
return typeMap;
}
}
因此,检查是否有更有效的解决方案:
if (modelMapper.getTypeMap(User.class,GetUserDto.class) == null){
modelMapper.createTypeMap(User.class, GetUserDto.class).setConverter(converter);
}
return modelMapper.map(user, GetUserDto.class);
现在,如果您确实希望避免不必要的处理,则可以创建TypeMap并将所有与之关联的转换器设置为在特定类中一次。
public void initTypeMaps(){
modelMapper.createTypeMap(User.class, GetUserDto.class).setConverter(converterUserAndUserDto);
modelMapper.createTypeMap(Other.class, GetOtherDto.class).setConverter(converterOtherAndOtherDto);
...
}
最后,如果您在短时间内对该方法有数千次调用,并且想要最大程度地减少开销,请不要使用ModelMapper和转换器,而要在两个类之间进行映射。