生成されたマッパー実装にスプリングサービスクラスを挿入する必要があります。
@Mapping(target="x", expression="Java(myservice.findById(id))")"
これはMapstruct-1.0に適用可能ですか?
Springをコンポーネントモデルとして宣言し、myservice
の型への参照を追加すると可能になります。
@Mapper(componentModel="spring", uses=MyService.class)
public interface MyMapper { ... }
このメカニズムは、生成されたコードによって呼び出される他のマッピングメソッドへのアクセスを提供することを目的としていますが、その方法でも式で使用できるはずです。サービス参照で生成されたフィールドの正しい名前を使用していることを確認してください。
Brettanomycesがコメントしているように、式以外のマッピング操作で使用されない場合、サービスは注入されません。
私がこれを見つけた唯一の方法は:
私はCDIを使用していますが、Springと同じでなければなりません:
@Mapper(
unmappedTargetPolicy = org.mapstruct.ReportingPolicy.IGNORE,
componentModel = "spring",
uses = {
// My other mappers...
})
public abstract class MyMapper {
@Autowired
protected MyService myService;
@Mappings({
@Mapping(target="x", expression="Java(myservice.findById(obj.getId())))")
})
public abstract Dto myMappingMethod(Object obj);
}
1.2以降、これは@AfterMappingと@Contextの組み合わせで解決できます。このように:
@Mapper(componentModel="spring")
public interface MyMapper {
@Mapping(target="x",ignore = true)
// other mappings
Target map( Source source, @Context MyService service);
@AfterMapping
default void map( @MappingTarget Target.X target, Source.ID source, @Context MyService service) {
target.set( service.findById( source.getId() ) );
}
}
サービスはコンテキストとして渡すことができます。
より良い解決策は、MyService
を直接渡す代わりに、MyService
をラップする@Context
クラスを使用することです。 @AfterMapping
メソッドは、この「コンテキスト」クラスに実装できます。void map( @MappingTarget Target.X target, Source.ID source )
マッピングロジックをルックアップロジックから解放します。 MapStruct example repository でこの例を確認してください。
上記の回答に加えて追加する価値があるのは、mapstruct mapperでspringサービスを使用するよりクリーンな方法があることです。これは、「修飾子」と呼ばれる「関心の分離」設計コンセプトにより適合します。簡単にするために、ここに記載されている名前付き修飾子を好みます http://mapstruct.org/documentation/stable/reference/html/#selection-based-on-qualifiers 例は次のようになります:
import org.mapstruct.Named;
import org.springframework.stereotype.Component;
@Component
public class EventTimeQualifier {
private EventTimeFactory eventTimeFactory; // ---> this is the service you want yo use
public EventTimeQualifier(EventTimeFactory eventTimeFactory) {
this.eventTimeFactory = eventTimeFactory;
}
@Named("stringToEventTime")
public EventTime stringToEventTime(String time) {
return eventTimeFactory.fromString(time);
}
}
これは、マッパーでの使用方法です。
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper(componentModel = "spring", uses = EventTimeQualifier.class)
public interface EventMapper {
@Mapping(source = "checkpointTime", target = "eventTime", qualifiedByName = "stringToEventTime")
Event map(EventDTO eventDTO);
}