为映射项生成 ID

Generate ID for mapped item

在我们的项目中,习惯上所有映射都使用mapstruct。在这种独特的情况下,我不是在创建实体,而是在创建 DTO。但是这个 DTO 需要我生成一个 UUID,我宁愿不使用表达式选项。

@Mapping(target = "trackId", expression = "java(UUID.randomUUID().toString())")
FileUploadRequest inventoryToFileUpload(Inventory inventory);

我宁愿把编译器当成生活中的朋友。另外,如果生成策略不是 30 个字符宽度的一行,你会怎么做?

我的首选方法如下:

@Mapping(target = "trackId", qualifiedByName = "generateUUID"),
FileUploadRequest inventoryToFileUpload(Inventory inventory);


@Named("generateUUID")
default String generateUuid() {
    return UUID.randomUUID().toString();
}

很遗憾,上面的方法不起作用。还得给个出处,废话。或者也许有一种方法可以指定我不依赖任何参数?

这是有效的代码:

// Ommiting other mappings for clarity
@Mapping(target = "trackId", source = "id", qualifiedByName = "generateUUID")
FileUploadRequest inventoryToFileUpload(Inventory inventory);

@Named("generateUUID")
default String generateUuid(final String nonsense) {
    return UUID.randomUUID().toString();
}

这会生成以下代码行

fileUploadRequest.setTrackId(this.generateUuid(inventory.getId()));

但是...参数是多余的,很容易看出。我知道这 ACTUALLY 无关紧要。但这似乎是一个疏忽,或者我不明白如何声明我没有这方面的来源,我只是想让映射器调用我的方法。

再次强调,expression不是有效答案,请勿提出。除非你能做到 expression = "java(generateUuid())"?

MapStruct 是关于不同对象之间的映射。这就是为什么你不能使用空方法(没有 expression)。

我的建议是确实使用 Mapping#expression。但是,为了简化它,您可以使用类似的东西:

public class MappingUtils {

    public static String GENERATE_UUID_EXPRESSION = "java(" + MappingUtils.class.getCanonicalName() + ".generateUuid())"


    public static String generateUuid() {
        return UUID.randomUUID().toString();
    }

}

然后在您的映射器中您可以执行以下操作:

@Mapper
public interface MyMapper {

    @Mapping(target = "trackId", expression = MappingUtils. GENERATE_UUID_EXPRESSION)
    FileUploadRequest inventoryToFileUpload(Inventory inventory);

}

这样做,您在一个地方就有了表达式,并且您有一个执行生成的方法。

生成的代码将使用 MappingUtils 的完整限定名。如果您想避免这种情况,您需要将 MappingUtils 添加到 Mapper#imports,然后在表达式中使用 MappingUtils.class.getName()