【发布时间】:2016-07-30 15:11:04
【问题描述】:
我在 SO 中寻找过类似的问题,虽然我发现了一些相关问题,但没有一个得到回答。所以我在这里发布我的问题,希望能有更好的运气。
我有一个父记录 Resource 和孩子(一对多)ResourceSkills。我可以在用于编辑资源的 Thymeleaf 页面上显示 Resource 和 ResourceSkills 的值,但是在保存时,我在控制器类中看到 ResourceSkills 为 Null。这会导致 NullPointerException。
代码如下:
资源
@Entity
public class Resource {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Version
private Integer version;
private String firstName;
private String lastName;
@OneToMany (mappedBy = "resource", orphanRemoval=false, fetch=FetchType.EAGER)
private List<ResourcesSkills> skills;
@ManyToOne (fetch=FetchType.EAGER)
@JoinColumn(name="project_id")
private Project project;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public List<ResourcesSkills> getSkills() {
return skills;
}
public void setSkills(List<ResourcesSkills> skills) {
this.skills = skills;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
public Project getProject() {
return project;
}
public void setProject(Project project) {
this.project = project;
}
}
资源技能
@Entity
@IdClass(ResourcesSkillsId.class)
public class ResourcesSkills {
@Id
@ManyToOne
@JoinColumn(name="resource_id")
private Resource resource;
@Id
@ManyToOne
@JoinColumn(name = "skill_id")
private Skill skill;
@Version
private Integer version;
private boolean primarySkill;
public Resource getResource() {
return resource;
}
public void setResource(Resource resource) {
this.resource = resource;
}
public Skill getSkill() {
return skill;
}
public void setSkill(Skill skill) {
this.skill = skill;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
public boolean isPrimarySkill() {
return primarySkill;
}
public void setPrimarySkill(boolean primarySkill) {
this.primarySkill = primarySkill;
}
}
资源控制器
@Controller
public class ResourceController {
ResourceService resourceService;
SkillService skillService;
@Autowired
public void setResourceService(ResourceService resourceService){
this.resourceService = resourceService;
}
@Autowired
public void setSkillService(SkillService skillService){
this.skillService = skillService;
}
@RequestMapping(value="resources", method = RequestMethod.GET)
public String list(Model model){
model.addAttribute("resources", resourceService.listAllResources());
return "resources";
}
@RequestMapping(value="resource/{id}")
public String showResource(@PathVariable Integer id, Model model){
model.addAttribute("resource", resourceService.getResourceById(id));
return "resourceshow";
}
@RequestMapping(value = "resource/new")
public String newResource(Model model){
model.addAttribute("resource", new Resource());
model.addAttribute("skills", skillService.listAllSkills());
return "resourceform";
}
@RequestMapping(value = "resource/edit/{id}")
public String editResource(@PathVariable Integer id, Model model){
Resource resource = resourceService.getResourceById(id);
model.addAttribute("resource", resource);
return "resourceform";
}
@RequestMapping(value = "resource/delete/{id}")
public String deleteResource(@PathVariable Integer id){
resourceService.deleteResource(id);
return "redirect:/resources";
}
@RequestMapping(value = "resource", method = RequestMethod.POST)
public String saveResource(Resource resource){
/* AT THIS POINT resource.skills is NULL and save FAILS */
ResourceService.saveResource(resource);
return "redirect:/resource/" + resource.getId();
}
}
最后是 Thymeleaf 代码:
<h2>Resource Details</h2>
<div>
<form class="form-horizontal" th:object="${resource}" th:action="@{/resource}" method="post">
<input type="hidden" th:field="*{id}"/>
<input type="hidden" th:field="*{version}"/>
<div class="form-group">
<label class="col-sm-2 control-label">First name:</label>
<div class="col-sm-10">
<input type="text" class="form-control" th:field="*{firstName}"/>
</div>
<label class="col-sm-2 control-label">Surname:</label>
<div class="col-sm-10">
<input type="text" class="form-control" th:field="*{lastName}"/>
</div>
</div>
<div>
<table class="table table-stripped">
<tr>
<th>Skill</th>
<th>Primary</th>
</tr>
<tr th:each="resSkill : *{skills}">
<td th:text="${resSkill.skill.description}">Skill Description</td>
<td><input type="checkbox" name="primary" th:disabled="disabled" th:checked="${resSkill.primarySkill}" /></td>
</tr>
</table>
<a th:href="${'/resourceSkills/' + resource.id}">Edit Skills</a>
</div>
<div class="row">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</form>
</div>
我得到的错误如下(供参考):
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException: null
at eu.kororos.ccplanner.controllers.ResourceController.saveResource(ResourceController.java:79) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_65]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_65]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_65]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_65]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
【问题讨论】:
标签: java spring spring-boot spring-data-jpa thymeleaf