I’m trying to create a many-to-one base, but when adding via .jsp gives an error, via H2 console everything adds ok!
Please help me understand how to properly create a many-to-one relationship. It seems I got it wrong somewhere, or the problem is in the .jsp itself. Because as I said via the H2 console everything works well!
Thank you in advance!
My Group:
@Entity @Table(name = "PARTY") public class Group { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; @Column(name = "Name", nullable = false) private String name; @OneToMany(targetEntity = Team.class, mappedBy = "group", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private List<Team> teams = new ArrayList<>(); public Group() { }
My group controller:
@Controller @RequestMapping(value = "group") public class GroupController { private final GroupService groupService; @Autowired public GroupController(GroupService groupService) { this.groupService = groupService; } @GetMapping(value = "/group-list") public String findAllGroup(Model model) { model.addAttribute("partys", groupService.findAll()); return "groupList"; } @GetMapping(value = "/delete") public String deleteGroup(@RequestParam("id") Long id) { groupService.deleteById(id); return "redirect:/group/group-list"; } @GetMapping(value = "/showform") public String showFormForSave(Model model) { Group group = new Group(); model.addAttribute("group", group); return "groupForm"; } @PostMapping(value = "/saveGroup") public String saveGroup(@ModelAttribute("group") Group group) { groupService.saveGroup(group); return "redirect:/group/group-list"; } }
My Team:
@Entity @Table(name = "TEAM") public class Team { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; @Column(name = "name", nullable = false) private String name; @Column(name = "win") private Integer win; @Column(name = "draws") private Integer draws; @Column(name = "loss") private Integer loss; @Column(name = "goal") private Integer goal; @Column(name = "miss") private Integer miss; @Column(name = "point") private Integer point; @ManyToOne @JoinColumn(name = "group_id", referencedColumnName = "id", insertable = false, updatable = false) private Group group; public Team() { }
My TeamController:
@Controller @RequestMapping(value = "team") public class TeamController { private final TeamService teamService; @Autowired public TeamController(TeamService teamService) { this.teamService = teamService; } @GetMapping(value = "/team-list") public String findAllTeam(Model model) { model.addAttribute("teams", teamService.findAll()); return "teamList"; } @GetMapping(value = "/delete") public String deleteTeam(@RequestParam("id") Long id) { teamService.deleteById(id); return "redirect:/team/team-list"; } @GetMapping(value = "/showform") public String showFormForSave(Model model) { Team team = new Team(); model.addAttribute("team", team); return "teamForm"; } @PostMapping(value = "/saveTeam") public String saveTeam(@ModelAttribute("team") Team team) { teamService.saveTeam(team); return "redirect:/team/team-list"; } }
My .jsp form:
<html> <head> <title>Team form</title> </head> <body> <form:form method="post" action="/team/saveTeam" modelAttribute="team"> <form:hidden path="id"/> <div> <label>Name</label> <form:input path="name" id="name"/> </div> <div> <label>Win</label> <form:input path="win" id="win"/> </div> <div> <label>Draws</label> <form:input path="draws" id="draws"/> </div> <div> <label>Loss</label> <form:input path="loss" id="loss"/> </div> <div> <label>Goal</label> <form:input path="goal" id="goal"/> </div> <div> <label>Miss</label> <form:input path="miss" id="miss"/> </div> <div> <label>Point</label> <form:input path="point" id="point"/> </div> <div> <label>Group</label> <form:input path="group" id="group"/> </div> <form:button>Submit</form:button> <button onclick="window.history.back()" type="button">Cancel</button> </form:form> </body> </html>
Exception:
2020-07-19 21:57:42.705 WARN 9228 --- [nio-8080-exec-9] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors Field error in object 'team' on field 'group': rejected value [1]; codes [typeMismatch.team.group,typeMismatch.group,typeMismatch.org.example.championshipFootball.model.Group,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [team.group,group]; arguments []; default message [group]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'org.example.championshipFootball.model.Group' for property 'group'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'org.example.championshipFootball.model.Group' for property 'group': no matching editors or conversion strategy found]]
Advertisement
Answer
You should make it a bidirectional relation, should add a @OneToMany
annotation to your Group entity, like so:
@OneToMany(fetch=FetchType.LAZY, mappedBy="group") private Team team;
then, if you type just Group’s id in your jsp input, you have to create a Converter (id->Group), i.e.:
@Component public class GroupIdToGroupConverter implements Converter<Integer, Group> { @Override public Group convert(Integer source) { return groupRepository.findById(source); //or any other way you get your entities (entity manager, etc...) } }