我正在使用SpringMVC和SpringJPA。而且我更喜欢使用REST风格,即使我没有开发Web服务。
在我使用Thymeleaf的前端,在后端我有一个实体/模型项目,如:
@Entity
@Table(name = "projects")
public class Project extends AbstractPersistable<Long> {
private static final long serialVersionUID = 7075433538058077502L;
@Size(min = 2, max = 30)
@NotBlank
private String name;
@NotNull
@Enumerated(EnumType.STRING)
private ProjectCategory category;
@Temporal(TemporalType.DATE)
@NotNull
@DateTimeFormat(iso = ISO.DATE)
private Date startDate;
@Temporal(TemporalType.DATE)
@NotNull
@DateTimeFormat(iso = ISO.DATE)
private Date endDate;
在AbstractPersistable中,setId方法受到保护,因此我无法将id目录设置为此实体。 (我知道我可以覆盖setId方法,但我认为这不是对id进行操作的正确方法,必须有一些原因可以解释为什么SpringJPA将setId方法定义为受保护。)
我的控制器就像:
@RequestMapping(value = "/{id}/edit", method = RequestMethod.GET)
public String edit(@PathVariable("id") Long id, Model model) {
model.addAttribute("project", projectService.find(id));
return "projects/edit";
}
@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public ModelAndView update(@PathVariable("id") Long id, @Valid Project project, BindingResult result, RedirectAttributes redirect) {
if (result.hasErrors()) {
return new ModelAndView("projects/edit");
}
try {
projectService.update(project);
logger.info(project.getName() + " project has been updated.");
redirect.addFlashAttribute(GLOBAL_MESSAGE, "Project updated successfully.");
} catch (BusinessException e) {
ModelAndView view = new ModelAndView("projects/edit");
view.addObject(BUSINESS_ERROR, e.getMessage());
return view;
}
return new ModelAndView(redirectTo("/projects"));
}
现在,在我的控制器中,SpringMVC无法设置Project对象的id。一个问题是,如果BindingResult中存在一些错误,我需要使用没有id值的Project对象将请求转发到'projects / edit'视图,以允许用户输入正确的项目信息。
我的观点表格如下:
<form id="project-form" th:action="@{'/projects/' + ${project.id}}" th:object="${project}" th:method="put" class="form-horizontal">
</form>
然后,表单标记中的action属性将不具有项目的id值。由于操作是/ projects / null
,因此用户无法在更正错误后重新提交表单如何正确使用SpringMVC,SpringJPA和REST风格?对我来说,有没有关于SpringMVC API的误解?
是否有任何示例和开源项目具有SpringMVC和SpringJPA的完整CRUD?
答案 0 :(得分:0)
我也一直面临着这个问题。似乎有两种方法:
我已经覆盖了我的setId;)
编辑:
在与其他形式的斗争后,我有一个很好的解决方案。我用了一个活页夹。在控制器类中,我已初始化它:
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Player.class, new PropertyEditorSupport() {
@Override
public void setAsText(String text) {
Player custom = repositoryPlayerService.findById(Integer.parseInt(text));
setValue(custom);
}
});
}
在FORM标签的JSP中:
<form:form id="updatePlayerForm" action='' modelAttribute="player" method="post">
....
<input id="player" type="hidden" name="player" value="${player.id}" />
....
</form:form>
通过这种方式,您将获得一个实体(您正在使用的数据对象),并在控制器的POST方法中填写了一个ID。