如何在MapStruct中设置Instant字段为当前时间now()?
问题:MapStruct设置Instant类型createdAt字段为当前时间失败
我的POJO类中有一个Instant类型的createdAt字段,希望创建记录时自动设为当前时间(now()),用MapStruct实现时配置出错。
Mapper代码
@Mapper(componentModel = "spring", imports = {Instant.class}) public interface CreatePostRequestMapper { // @Mapping(target = "createdAt", defaultExpression ="java(Instant.now())") @Mapping(target = "createdAt", defaultValue = "java(Instant.now())") Post toEntity(CreatePostRequest source); CreatePostRequest toDto(Post destination); }
Post和CreatePostRequest类均包含同名的私有Instant createdAt属性。
服务方法代码
private final CreatePostRequestMapper createPostRequestMapper; public PostDetails createPost(@Valid CreatePostRequest request) { final Post post = createPostRequestMapper.toEntity(request); // 代码省略 }
运行时错误
Request processing failed; nested exception is java.time.format.DateTimeParseException: Text 'java(Instant.now())' could not be parsed at index 0] with root cause
解决方法
问题根源
你混淆了MapStruct的两个注解属性:defaultValue是用来设置字符串常量默认值的,MapStruct会把你写的"java(Instant.now())"当作普通字符串去转成Instant类型,自然触发日期解析错误。而要执行Java代码表达式,得用defaultExpression属性。
正确配置
把注解改成defaultExpression即可:
@Mapper(componentModel = "spring", imports = {Instant.class}) public interface CreatePostRequestMapper { @Mapping(target = "createdAt", defaultExpression = "java(Instant.now())") Post toEntity(CreatePostRequest source); CreatePostRequest toDto(Post destination); }
额外说明
defaultExpression接收合法的Java代码片段,MapStruct会直接把这段代码生成到映射方法里- 因为已经在
@Mapper的imports中引入了Instant,所以表达式里不用写全限定类名java.time.Instant.now() - 如果你的业务场景中,
CreatePostRequest的createdAt可能存在非null值,需要覆盖的话,可以用expression属性,但创建记录的场景下,defaultExpression更合适——只有当源对象的createdAt为null时,才会执行表达式设置当前时间
内容的提问来源于stack exchange,提问作者user21263160
相关产品推荐
相关产品推荐

