2017-06-29 5 views
0

Ich habe die follwoing Code ein Objekt der Klasse User seiner DTO vom Typ zur Umwandlung GetUserDto:einen Konverter für ModelMapper Set nur einmal

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); 
} 

Es funktioniert zum ersten Mal in Ordnung, aber die nachfolgenden Anrufe an convertToDto wirft:

java.lang.IllegalStateException: A TypeMap already exists for class com.boot.cut_costs.model.User and class com.boot.cut_costs.dto.user.ExtendedGetUserDto

ich einige andere Beiträge bezüglich dieser gefunden, schlug man überprüfen TypeMap für modelMapper null und nicht zu schaffen es wieder, wenn es nicht null war. Dies ist keine gute Lösung, als ob Sie Tausende von Aufrufen zu dieser Methode unnötigen Overhead hinzufügen würden.

Eine gute Lösung?

+0

Wie über Split-Konverter init und konvertieren Logik? Init alle Ihre Konverter nur einmal beim Start und verwenden Sie einfach 'return modelMapper.map (Benutzer, GetUserDto.class);' – StanislavL

+0

Wie kann ich automatisch zum Zeitpunkt der Erstellung init? Es ist eine Servicekomponente (d. H. Die Klasse, die den Konverter enthält, ist mit "@ Service" versehen). –

+0

Spezifizieren Sie eine Annotation wie das Scan-Paket, das auf Pakete zielt. Gehen Sie alle Klassen aus dem Paket durch und fügen Sie eine Klasseninstanz von Converter dem Mapper hinzu. – StanislavL

Antwort

1

Ich fand einige andere Beiträge in Bezug auf diese, schlug vor, null TypeMap für ModelMapper zu überprüfen und nicht erneut zu erstellen, wenn es nicht null war. Dies ist keine gute Lösung, als wenn Sie Tausende von Anrufen zu dieser Methode haben, fügt es unnötigen Overhead hinzu.

Wenn Sie den Code schauen Sie in der org.modelmapper.ModelMapper.getTypeMap() und org.modelmapper.ModelMapper.createTypeMap(), werden Sie sehen, dass eine TypeMap schaffen, die eine höhere Aufwand ist als einfach eine Methode den Aufruf einer TypeMap abzurufen.

das Objekt aus einer Karte zurückkehrend, wenn es gerade vorhanden ist:

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); 
    } 

Während die Zugabe führt viel mehr Dinge.
Es schafft einen Proxy-Typ, hat eine synchronisierte Aufgabe und hat einige überprüft, bevor sie eine TypeMap Instanz und schließlich die Schaffung es bringt es auf der Karte:

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); 
    } 

, die auch ruft:

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; 
    } 
    } 

So Überprüfen Sie, ob eine effizientere Lösung:

if (modelMapper.getTypeMap(User.class,GetUserDto.class) == null){ 
    modelMapper.createTypeMap(User.class, GetUserDto.class).setConverter(converter); 
} 
return modelMapper.map(user, GetUserDto.class); 

Nun, wenn Sie wirklich unnötige Verarbeitung vermeiden möchten, könnten Sie cre aß die TypeMap und setze alle Konverter, die zu einer bestimmten Klasse gehören, einmal.

public void initTypeMaps(){ 
     modelMapper.createTypeMap(User.class, GetUserDto.class).setConverter(converterUserAndUserDto); 
     modelMapper.createTypeMap(Other.class, GetOtherDto.class).setConverter(converterOtherAndOtherDto); 
... 
} 

Endlich, wenn Sie Tausende von Anrufen zu dieser Methode in kurzer Zeit und Sie wollen das Maximum der Aufwand zu reduzieren, verwenden Sie keine ModelMapper und einen Konverter, sondern tun, um die Zuordnung zwischen zwei Klassen verfügbar.

Verwandte Themen