使用 java 代码而不是 mapstruct 表达式
use java code instead of mapstruct expression
我正在学习使用MapStruct。
我有以下自定义映射配置,它以这种方式将来自 JPA 实体的 List
映射到 DTO String
:
@Mapper(componentModel = "spring")
public interface StatusMapper {
@Mapping(target = "statusCode",
expression = "java(entity.getStatuses().get(entity.getStatuses().size() - 1).getStatus())")
@Mapping(target = "details",
expression = "java(entity.getStatuses().get(entity.getStatuses().size() - 1).getMessage())")
StatusResponse map(MyEntity entity);
}
我对这个解决方案的问题是 expression
中的 Java 代码实际上是一个字符串,而 IDE(例如 IntelliJ)没有检查这个“java" 代码。
也许重构后这段代码将不再起作用,因为我重命名了相关字段。
如果我在表达式中添加一个 null
检查,那么这段代码将会更长,而更长的代码可能会有更多的拼写错误。
我可以在这里写一个真正的 java 代码而不是使用这个 Java 表达式字符串吗?
记住MapStruct是注解处理器,写在expression
中的表达式会在生成的Javaclass中一一对应。因此,进行重构会导致编译错误。
话虽如此,但有一个替代解决方案。
@Mapper(componentModel = "spring")
public interface StatusMapper {
@Mapping(target = "statusCode", source = "statuses", qualifiedByName = "statusesStatus")
@Mapping(target = "details", source = "statuses", qualifiedByName = "statusesMessage")
StatusResponse map(MyEntity entity);
@Named("statusesStatus")
default String extractStatus(Collection<Status> statuses) {
return statuses != null && statuses.isEmpty() ? statuses.get(statuses.get() - 1).getStatus() : null;
}
@Named("statusesMessage")
default String extractStatusMessage(Collection<Status> statuses) {
return statuses != null && !statuses.isEmpty() ? statuses.get(statuses.get() - 1).getMessage() : null;
}
}
这样做将确保 MapStruct 使用您定义的自定义方法。
另一个可能不错的解决方案(MapStruct 中尚不存在)并且有一个开放的功能请求是 Allowing indexing for object list。
可能的解决方案如下所示:
@Mapper(componentModel = "spring")
public interface StatusMapper {
@Mapping(target = "statusCode", source = "statuses[-1].status")
@Mapping(target = "details", source = "statuses[-1].message")
StatusResponse map(MyEntity entity);
}
如果您对此感兴趣,我建议您就此问题进行投票。
我正在学习使用MapStruct。
我有以下自定义映射配置,它以这种方式将来自 JPA 实体的 List
映射到 DTO String
:
@Mapper(componentModel = "spring")
public interface StatusMapper {
@Mapping(target = "statusCode",
expression = "java(entity.getStatuses().get(entity.getStatuses().size() - 1).getStatus())")
@Mapping(target = "details",
expression = "java(entity.getStatuses().get(entity.getStatuses().size() - 1).getMessage())")
StatusResponse map(MyEntity entity);
}
我对这个解决方案的问题是 expression
中的 Java 代码实际上是一个字符串,而 IDE(例如 IntelliJ)没有检查这个“java" 代码。
也许重构后这段代码将不再起作用,因为我重命名了相关字段。
如果我在表达式中添加一个 null
检查,那么这段代码将会更长,而更长的代码可能会有更多的拼写错误。
我可以在这里写一个真正的 java 代码而不是使用这个 Java 表达式字符串吗?
记住MapStruct是注解处理器,写在expression
中的表达式会在生成的Javaclass中一一对应。因此,进行重构会导致编译错误。
话虽如此,但有一个替代解决方案。
@Mapper(componentModel = "spring")
public interface StatusMapper {
@Mapping(target = "statusCode", source = "statuses", qualifiedByName = "statusesStatus")
@Mapping(target = "details", source = "statuses", qualifiedByName = "statusesMessage")
StatusResponse map(MyEntity entity);
@Named("statusesStatus")
default String extractStatus(Collection<Status> statuses) {
return statuses != null && statuses.isEmpty() ? statuses.get(statuses.get() - 1).getStatus() : null;
}
@Named("statusesMessage")
default String extractStatusMessage(Collection<Status> statuses) {
return statuses != null && !statuses.isEmpty() ? statuses.get(statuses.get() - 1).getMessage() : null;
}
}
这样做将确保 MapStruct 使用您定义的自定义方法。
另一个可能不错的解决方案(MapStruct 中尚不存在)并且有一个开放的功能请求是 Allowing indexing for object list。
可能的解决方案如下所示:
@Mapper(componentModel = "spring")
public interface StatusMapper {
@Mapping(target = "statusCode", source = "statuses[-1].status")
@Mapping(target = "details", source = "statuses[-1].message")
StatusResponse map(MyEntity entity);
}
如果您对此感兴趣,我建议您就此问题进行投票。