【发布时间】:2018-11-11 07:55:41
【问题描述】:
用例:用户可以使用用 JavaScript 编写的单页 Web 应用程序对多项选择题进行 CRUD。
- 创建一个新问题并添加一些选项都发生在浏览器/前端 (FE) 中。
- FE 为问题和所有选项创建并使用临时 ID(“_1”、“_2”、...),直到用户单击保存按钮。
- 在保存新创建的问题时,FE 将包含 临时 ID 的 JSON 发送到后端
- 因此,FE 期望
201 CREATED包含一个映射 临时 id -> 后端 id 来更新其 id。 - 用户决定添加另一个 Option(在 FE 端再次使用临时 id)
- 用户点击保存,FE 发送更新后的问题,其中包含后端 ID(用于问题和现有选项)和临时 ID(用于新创建的选项)
- 要更新新创建的选项的 id,FE 希望响应包含此 id 的映射。
我们应该如何在后端实现最后一部分(5-7添加选项)的对应项?
我试试这个,但坚持后我无法获得孩子的ID。
实体
@Entity
public class Question {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(mappedBy = "config", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Option> options = new ArrayList<>();
// ...
}
@Entity
public class Option {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne
@JoinColumn(name = "question_id", nullable = false)
private Question question;
public Option(Long id, Config config) {
this.id = id;
this.question = question;
}
// ...
}
控制器
@RestController
@RequestMapping("/questions")
public class AdminQuestionsController {
@Autowired
private QuestionRepository questionRepo;
@Autowired
private OptionRepository optionRepo;
@PutMapping("/{id}")
@ResponseStatus(HttpStatus.OK)
public QuestionDTO updateQuestion(@PathVariable("id") String id, @RequestBody QuestionDTO requestDTO) {
Question question = questionRepo.findOneById(Long.parseLong(id));
// will hold a mapping of the temporary id to the newly created Options.
Map<String, Option> newOptions = new HashMap<>();
// update the options
question.getOptions().clear();
requestDTO.getOptions().stream()
.map(o -> {
try { // to find the existing option
Option theOption = question.getOptions().stream()
// try to find in given config
.filter(existing -> o.getId().equals(existing.getId()))
.findAny()
// fallback to db
.orElse(optionRepo.findOne(Long.parseLong(o.getId())));
if (null != theOption) {
return theOption;
}
} catch (Exception e) {
}
// handle as new one by creating a new one with id=null
Option newOption = new Option(null, config);
newOptions.put(o.getId(), newOption);
return newOption;
})
.forEach(o -> question.getOptions().add(o));
question = questionRepo.save(question);
// create the id mapping
Map<String, String> idMap = new HashMap<>();
for (Entry<String, Option> e : newOptions.entrySet()) {
idMap.put(e.getKey(), e.getValue().getId());
// PROBLEM: e.getValue().getId() is null
}
return QuestionDTO result = QuestionDTO.from(question, idMap);
}
}
在控制器中我标记了问题:e.getValue().getId() 为空
这样的控制器应该如何创建idMap?
【问题讨论】:
-
您能否描述一下您提供参数配置但您没有使用它而不是使用问题的选项构造函数,另一点是当您尝试处理新选项时,您再次使用配置null id,你能定义什么是配置以及它在你的代码中的使用方式
标签: spring spring-boot jpa spring-data spring-data-jpa