用例 :用户可以使用 JavaScript 编写的单页 Web 应用程序 CRUD 多项选择题。
201 CREATED
包含 map 临时 id -> 后端 id 以更新其 id。 我们应该如何在后端实现最后一部分的对应物(5-7 添加一个选项)?
我尝试了这个,但是在坚持之后我无法获得 child 的 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;
}
// ...
}
Controller
@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);
}
}
在 Controller 中我标记了问题:e.getValue().getId() is null
这样的 Controller 应该如何创建 idMap?
最佳答案
最好单独保存每个选项,然后将生成的 Id 保存在 map 上。
我做了下面的测试,效果很好。
@Autowired
void printServiceInstance(QuestionRepository questions, OptionRepository options) {
Question question = new Question();
questions.save(question);
question.add(new Option(-1L, question));
question.add(new Option(-2L, question));
question.add(new Option(-3L, question));
question.add(new Option(-4L, question));
Map<Long, Long> idMap = new HashMap<>();
question.getOptions().stream()
.filter(option -> option.getId() < 0)
.forEach(option -> idMap.put(option.getId(), options.save(option).getId()));
System.out.println(idMap);
}
控制台输出:
{-1=2, -2=3, -3=4, -4=5}
更新:
或者,如果前端只是控制选项的顺序,并根据未保存选项的顺序获取新的 id,那么这将是一个更好的代码风格。
选项:
@Column(name = "order_num")
private Integer order;
public Option(Long id, Integer order, Question question) {
this.id = id;
this.question = question;
this.order = order;
}
更新示例:
@Autowired
void printServiceInstance(QuestionRepository questions, OptionRepository options) {
Question question = new Question();
Question merged = questions.save(question);
merged.add(new Option(-1L, 1, merged));
merged.add(new Option(-2L, 2, merged));
merged.add(new Option(-3L, 3, merged));
merged.add(new Option(-4L, 4, merged));
questions.save(merged);
System.out.println(questions.findById(merged.getId()).get().getOptions());//
}
控制台输出: [选项[id=2, order=1], 选项[id=3, order=2], 选项[id=4, order=3], 选项[id=5, order=4]]
请注意,不需要映射来控制新 id,前端应该通过按选项的顺序获取它来知道。
关于spring - 如何将前端给出的临时 ID 映射到生成的后端 ID?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50638928/