Java 尝试定义自定义属性映射时出现NullPointerException
我使用ModelMapper的方式如下: 我有几个转换器类是Spring组件,它们注册自定义ModelMapper映射Java 尝试定义自定义属性映射时出现NullPointerException,java,spring,nullpointerexception,modelmapper,Java,Spring,Nullpointerexception,Modelmapper,我使用ModelMapper的方式如下: 我有几个转换器类是Spring组件,它们注册自定义ModelMapper映射 @Component public class FooConverter { @Autowired private ModelMapper modelMapper; public static final PropertyMap<Foo, FooModel> FOO_TO_FOO_MODEL_MAP = new PropertyMap&l
@Component
public class FooConverter {
@Autowired
private ModelMapper modelMapper;
public static final PropertyMap<Foo, FooModel> FOO_TO_FOO_MODEL_MAP = new PropertyMap<Foo, FooModel>() {
@Override
protected void configure() {
map().setTimeZone(source.getTimeZone().getID());
}
};
@PostConstruct
public void init() {
modelMapper.addMappings(FOO_TO_FOO_MODEL_MAP);
}
}
重要编辑
实际上,即使在主类内的函数中显式创建映射,也会得到相同的NullPointerException
public class main {
public static void main(String[] args) {
ModelMapper mapper = new ModelMapper();
final PropertyMap<Foo, FooModel> FOO_TO_FOO_MODEL_MAP = new PropertyMap<Foo, FooModel>() {
@Override
protected void configure() {
map().setTimeZone(source.getTimeZone().getID());
}
};
mapper.addMappings(FOO_TO_FOO_MODEL_MAP );
}
问题只在于时区对象,所以我必须使用转换器,这并不理想
map().setTimeZone(source.getTimeZone().getID());
public class Foo {
private TimeZone timeZone;
//Setters//Getters
}
public class FooModel {
private String timeZoneId;
//Setters//Getters
}
使用构造函数自动连线
像
还要确保ModelMapper bean已在spring配置类中定义,如下所示:
@Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}
我认为这最终是因为ModelMapper在配置映射器时不能实例化
TimeZone
对象(也不能实例化LocalDateTime
等)
实际上你不需要配置任何东西
ModelMapper mapper = new ModelMapper();
Foo foo = new Foo();
foo.setTimeZone(TimeZone.getDefault());
FooModel model = mapper.map(foo, FooModel.class);
System.out.println(model.getTimeZoneId()); // "Europe/Berlin" here
这对我有用。ModelMapper发现您想要将时区的属性ID
映射到FooModel
的属性timeZoneId
不过,如果您想手动执行此操作:
我很快就看完了文档,发现了。
使用将时区
转换为字符串
的转换器
,可以执行以下操作:
ModelMapper mapper = new ModelMapper();
TypeMap<Foo, FooModel> typeMap = mapper.createTypeMap(Foo.class, FooModel.class);
Converter<TimeZone, String> tzConverter = ctx -> ctx.getSource().getID() + "!!!";
typeMap.addMappings(map -> {
map.using(tzConverter).map(Foo::getTimeZone, FooModel::setTimeZoneId);
});
Foo foo = new Foo();
foo.setTimeZone(TimeZone.getDefault());
FooModel model = mapper.map(foo, FooModel.class);
System.out.println(model.getTimeZoneId()); // "Europe/Berlin!!!" here
ModelMapper-mapper=newmodelmapper();
TypeMap TypeMap=mapper.createTypeMap(Foo.class,FooModel.class);
转换器tzConverter=ctx->ctx.getSource().getID()+“!!!”;
typeMap.addMappings(映射->{
map.using(tzConverter.map)(Foo::getTimeZone,FooModel::setTimeZoneId);
});
Foo-Foo=新的Foo();
setTimeZone(TimeZone.getDefault());
FooModel model=mapper.map(foo,FooModel.class);
System.out.println(model.getTimeZoneId());//“欧洲/柏林!!!”在这里
对于遇到相同问题的人:我的问题是我使用了带有匿名实现的PropertyMap,就像spring配置中建议的文档一样。这在ExplicitMappingBuilder中搞砸了。我现在有以下资料:
@Configuration
public class ApplicationConfig {
@Bean
public ModelMapper modelMapper() {
ModelMapper modelMapper = new ModelMapper();
modelMapper.addMappings(new UserPropertyMap());
return modelMapper;
}
}
我的UserPropertyMap如下所示:
public class UserPropertyMap extends PropertyMap<UserRepresentation, UserDTO> {
@Override
protected void configure() {
map().setUserName(source.getUsername());
}
}
公共类UserPropertyMap扩展了PropertyMap{
@凌驾
受保护的void configure(){
map().setUserName(source.getUsername());
}
}
这就像Spring Boot 2中的魅力一样。基于构造函数的连接只会使bean的缺乏更加明显,但是如果bean被正确定义和连接,你就无法区分基于字段的连接和基于构造函数的连接。这是在修复一个症状。它总是倾向于使用基于Construtor的接线。它确保在为类创建Bean之前初始化注入Beannull@SayantanMandal在现实世界中,基于构造函数的布线变得非常困难!您的modelMapper
bean在哪里定义?@Makoto问题已更新。bean的定义是正确的,它不是nullIsFoo
或FooModel
声明为final
?@JanRieke不,它们不是。您说过映射可以用于那些示例类InnerFoo,Foo l,FooModel
。您能为FooModel
添加一个无法映射的示例吗?谢谢。我最终使用了一个转换器。
ModelMapper mapper = new ModelMapper();
Foo foo = new Foo();
foo.setTimeZone(TimeZone.getDefault());
FooModel model = mapper.map(foo, FooModel.class);
System.out.println(model.getTimeZoneId()); // "Europe/Berlin" here
ModelMapper mapper = new ModelMapper();
TypeMap<Foo, FooModel> typeMap = mapper.createTypeMap(Foo.class, FooModel.class);
Converter<TimeZone, String> tzConverter = ctx -> ctx.getSource().getID() + "!!!";
typeMap.addMappings(map -> {
map.using(tzConverter).map(Foo::getTimeZone, FooModel::setTimeZoneId);
});
Foo foo = new Foo();
foo.setTimeZone(TimeZone.getDefault());
FooModel model = mapper.map(foo, FooModel.class);
System.out.println(model.getTimeZoneId()); // "Europe/Berlin!!!" here
@Configuration
public class ApplicationConfig {
@Bean
public ModelMapper modelMapper() {
ModelMapper modelMapper = new ModelMapper();
modelMapper.addMappings(new UserPropertyMap());
return modelMapper;
}
}
public class UserPropertyMap extends PropertyMap<UserRepresentation, UserDTO> {
@Override
protected void configure() {
map().setUserName(source.getUsername());
}
}