Vaadin 23中使用Binder绑定嵌套DTO出现空指针的解决方法咨询
Vaadin Binder处理嵌套DTO空指针问题的解决方案
问题根源
直接链式调用嵌套DTO的get方法(比如job.getOutputSource().getConnection().getDbUrl())时,如果中间任何一层对象(outputSource或connection)未初始化(为null),就会触发空指针异常。
解决方案
1. 提前初始化所有嵌套DTO对象
在JobDto及嵌套的OutputSourceDto、ConnectionDto的无参构造方法中,直接初始化内部对象,确保链式调用时不会出现null。
修改JobDto:
@AllArgsConstructor @NoArgsConstructor @Data public class JobDto { private Long jobId; private String jobName; private String jobDesc; private String status; private boolean isScheduled; private String cronExpression; // 初始化嵌套对象 private InputSourceDto inputSource = new InputSourceDto(); private OutputSourceDto outputSource = new OutputSourceDto(); }
对应的OutputSourceDto也要初始化内部的ConnectionDto:
@AllArgsConstructor @NoArgsConstructor @Data public class OutputSourceDto { private String type; // 初始化Connection对象 private ConnectionDto connection = new ConnectionDto(); // 其他字段... }
ConnectionDto同理,确保所有需要访问的属性对应的对象都已初始化。
2. 使用Vaadin Binder的嵌套属性路径绑定
Vaadin Binder支持用点分隔的属性路径绑定嵌套字段,语法更简洁,配合提前初始化的对象,能避免手动lambda的空指针问题:
jobBinder.bind(jobName, JobDto::getJobName, JobDto::setJobName); jobBinder.bind(jobDesc, JobDto::getJobDesc, JobDto::setJobDesc); // 嵌套属性路径绑定 jobBinder.forField(jobType).bind("outputSource.type"); jobBinder.forField(dbUrl).bind("outputSource.connection.dbUrl"); jobBinder.forField(dbUserName).bind("outputSource.connection.dbUserName"); jobBinder.forField(dbUserPassword).bind("outputSource.connection.dbUserPassword"); jobBinder.forField(dbDriverClass).bind("outputSource.connection.dbDriverClass"); jobBinder.bind(cronExpression, JobDto::getCronExpression, JobDto::setCronExpression);
3. 在绑定Lambda中添加空值检查(适合不提前初始化的场景)
如果不想提前初始化嵌套对象,可以在绑定的读写lambda中逐层检查null,必要时创建新对象:
// 绑定jobType的示例 jobBinder.forField(jobType) .bind( // 读取时处理null job -> Optional.ofNullable(job.getOutputSource()) .map(OutputSourceDto::getType) .orElse(null), // 写入时初始化空对象 (job, jobType) -> { if (job.getOutputSource() == null) { job.setOutputSource(new OutputSourceDto()); } job.getOutputSource().setType(jobType); } ); // 绑定dbUrl的示例(更深层级) jobBinder.forField(dbUrl) .bind( job -> Optional.ofNullable(job.getOutputSource()) .map(OutputSourceDto::getConnection) .map(ConnectionDto::getDbUrl) .orElse(null), (job, dbUrl) -> { if (job.getOutputSource() == null) { job.setOutputSource(new OutputSourceDto()); } OutputSourceDto output = job.getOutputSource(); if (output.getConnection() == null) { output.setConnection(new ConnectionDto()); } output.getConnection().setDbUrl(dbUrl); } );
推荐方案
优先选择方案1+方案2,既保证对象不会为null,又能利用Vaadin原生的嵌套属性绑定语法,代码简洁且不易出错。
内容的提问来源于stack exchange,提问作者Buddhima Chamaranga
相关产品推荐
相关产品推荐

