mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-07-22 15:25:49 +00:00
Fix bug with replacing entities to DTO objects that were used as arguments of "@RequestMapping" methods on the controller.
This commit is contained in:
parent
27109010a5
commit
579b62a81c
8 changed files with 252 additions and 7 deletions
5
pom.xml
5
pom.xml
|
@ -58,6 +58,11 @@
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<artifactId>modelmapper</artifactId>
|
||||||
|
<groupId>org.modelmapper</groupId>
|
||||||
|
<version>RELEASE</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package org.springframework.samples.petclinic.configuration;
|
||||||
|
|
||||||
|
import org.modelmapper.ModelMapper;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class AppBean {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ModelMapper modelMapper() {
|
||||||
|
return new ModelMapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package org.springframework.samples.petclinic.dto;
|
||||||
|
|
||||||
|
public class OwnerDto {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String firstName;
|
||||||
|
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
private String city;
|
||||||
|
|
||||||
|
private String telephone;
|
||||||
|
|
||||||
|
public OwnerDto() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public OwnerDto(Long id, String firstName, String lastName, String address, String city, String telephone) {
|
||||||
|
this.id = id;
|
||||||
|
this.firstName = firstName;
|
||||||
|
this.lastName = lastName;
|
||||||
|
this.address = address;
|
||||||
|
this.city = city;
|
||||||
|
this.telephone = telephone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 String getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddress(String address) {
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCity() {
|
||||||
|
return city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCity(String city) {
|
||||||
|
this.city = city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTelephone() {
|
||||||
|
return telephone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTelephone(String telephone) {
|
||||||
|
this.telephone = telephone;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package org.springframework.samples.petclinic.dto;
|
||||||
|
|
||||||
|
import org.springframework.samples.petclinic.owner.Owner;
|
||||||
|
import org.springframework.samples.petclinic.owner.PetType;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
public class PetDto {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private LocalDate birthDate;
|
||||||
|
|
||||||
|
private PetType type;
|
||||||
|
|
||||||
|
private Owner owner;
|
||||||
|
|
||||||
|
public PetDto() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public PetDto(Long id, LocalDate birthDate, PetType type, Owner owner) {
|
||||||
|
this.id = id;
|
||||||
|
this.birthDate = birthDate;
|
||||||
|
this.type = type;
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDate getBirthDate() {
|
||||||
|
return birthDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBirthDate(LocalDate birthDate) {
|
||||||
|
this.birthDate = birthDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PetType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(PetType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Owner getOwner() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOwner(Owner owner) {
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package org.springframework.samples.petclinic.dto;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
public class VisitDto {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private LocalDate date;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
private Integer petId;
|
||||||
|
|
||||||
|
public VisitDto() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public VisitDto(Long id, LocalDate date, String description, Integer petId) {
|
||||||
|
this.id = id;
|
||||||
|
this.date = date;
|
||||||
|
this.description = description;
|
||||||
|
this.petId = petId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDate getDate() {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDate(LocalDate date) {
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPetId() {
|
||||||
|
return petId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPetId(Integer petId) {
|
||||||
|
this.petId = petId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -15,6 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.samples.petclinic.owner;
|
package org.springframework.samples.petclinic.owner;
|
||||||
|
|
||||||
|
import org.modelmapper.ModelMapper;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.samples.petclinic.dto.OwnerDto;
|
||||||
import org.springframework.samples.petclinic.visit.VisitRepository;
|
import org.springframework.samples.petclinic.visit.VisitRepository;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
|
@ -45,6 +48,9 @@ class OwnerController {
|
||||||
|
|
||||||
private VisitRepository visits;
|
private VisitRepository visits;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ModelMapper modelMapper;
|
||||||
|
|
||||||
public OwnerController(OwnerRepository clinicService, VisitRepository visits) {
|
public OwnerController(OwnerRepository clinicService, VisitRepository visits) {
|
||||||
this.owners = clinicService;
|
this.owners = clinicService;
|
||||||
this.visits = visits;
|
this.visits = visits;
|
||||||
|
@ -63,7 +69,8 @@ class OwnerController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/owners/new")
|
@PostMapping("/owners/new")
|
||||||
public String processCreationForm(@Valid Owner owner, BindingResult result) {
|
public String processCreationForm(@Valid OwnerDto ownerDto, BindingResult result) {
|
||||||
|
Owner owner = modelMapper.map(ownerDto, Owner.class);
|
||||||
if (result.hasErrors()) {
|
if (result.hasErrors()) {
|
||||||
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
|
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
|
||||||
}
|
}
|
||||||
|
@ -80,7 +87,8 @@ class OwnerController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/owners")
|
@GetMapping("/owners")
|
||||||
public String processFindForm(Owner owner, BindingResult result, Map<String, Object> model) {
|
public String processFindForm(OwnerDto ownerDto, BindingResult result, Map<String, Object> model) {
|
||||||
|
Owner owner = modelMapper.map(ownerDto, Owner.class);
|
||||||
|
|
||||||
// allow parameterless GET request for /owners to return all records
|
// allow parameterless GET request for /owners to return all records
|
||||||
if (owner.getLastName() == null) {
|
if (owner.getLastName() == null) {
|
||||||
|
@ -114,8 +122,10 @@ class OwnerController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/owners/{ownerId}/edit")
|
@PostMapping("/owners/{ownerId}/edit")
|
||||||
public String processUpdateOwnerForm(@Valid Owner owner, BindingResult result,
|
public String processUpdateOwnerForm(@Valid OwnerDto ownerDto, BindingResult result,
|
||||||
@PathVariable("ownerId") int ownerId) {
|
@PathVariable("ownerId") int ownerId) {
|
||||||
|
Owner owner = modelMapper.map(ownerDto, Owner.class);
|
||||||
|
|
||||||
if (result.hasErrors()) {
|
if (result.hasErrors()) {
|
||||||
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
|
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.samples.petclinic.owner;
|
package org.springframework.samples.petclinic.owner;
|
||||||
|
|
||||||
|
import org.modelmapper.ModelMapper;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.samples.petclinic.dto.OwnerDto;
|
||||||
|
import org.springframework.samples.petclinic.dto.PetDto;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
@ -40,6 +44,9 @@ class PetController {
|
||||||
|
|
||||||
private final OwnerRepository owners;
|
private final OwnerRepository owners;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ModelMapper modelMapper;
|
||||||
|
|
||||||
public PetController(PetRepository pets, OwnerRepository owners) {
|
public PetController(PetRepository pets, OwnerRepository owners) {
|
||||||
this.pets = pets;
|
this.pets = pets;
|
||||||
this.owners = owners;
|
this.owners = owners;
|
||||||
|
@ -66,7 +73,8 @@ class PetController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/pets/new")
|
@GetMapping("/pets/new")
|
||||||
public String initCreationForm(Owner owner, ModelMap model) {
|
public String initCreationForm(OwnerDto ownerDto, ModelMap model) {
|
||||||
|
Owner owner = modelMapper.map(ownerDto, Owner.class);
|
||||||
Pet pet = new Pet();
|
Pet pet = new Pet();
|
||||||
owner.addPet(pet);
|
owner.addPet(pet);
|
||||||
model.put("pet", pet);
|
model.put("pet", pet);
|
||||||
|
@ -74,7 +82,10 @@ class PetController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/pets/new")
|
@PostMapping("/pets/new")
|
||||||
public String processCreationForm(Owner owner, @Valid Pet pet, BindingResult result, ModelMap model) {
|
public String processCreationForm(OwnerDto ownerDto, @Valid PetDto petDto, BindingResult result, ModelMap model) {
|
||||||
|
Owner owner = modelMapper.map(ownerDto, Owner.class);
|
||||||
|
Pet pet = modelMapper.map(petDto, Pet.class);
|
||||||
|
|
||||||
if (StringUtils.hasLength(pet.getName()) && pet.isNew() && owner.getPet(pet.getName(), true) != null) {
|
if (StringUtils.hasLength(pet.getName()) && pet.isNew() && owner.getPet(pet.getName(), true) != null) {
|
||||||
result.rejectValue("name", "duplicate", "already exists");
|
result.rejectValue("name", "duplicate", "already exists");
|
||||||
}
|
}
|
||||||
|
@ -97,7 +108,9 @@ class PetController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/pets/{petId}/edit")
|
@PostMapping("/pets/{petId}/edit")
|
||||||
public String processUpdateForm(@Valid Pet pet, BindingResult result, Owner owner, ModelMap model) {
|
public String processUpdateForm(@Valid PetDto petDto, BindingResult result, OwnerDto ownerDto, ModelMap model) {
|
||||||
|
Pet pet = modelMapper.map(petDto, Pet.class);
|
||||||
|
Owner owner = modelMapper.map(ownerDto, Owner.class);
|
||||||
if (result.hasErrors()) {
|
if (result.hasErrors()) {
|
||||||
pet.setOwner(owner);
|
pet.setOwner(owner);
|
||||||
model.put("pet", pet);
|
model.put("pet", pet);
|
||||||
|
|
|
@ -19,6 +19,9 @@ import java.util.Map;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
import org.modelmapper.ModelMapper;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.samples.petclinic.dto.VisitDto;
|
||||||
import org.springframework.samples.petclinic.visit.Visit;
|
import org.springframework.samples.petclinic.visit.Visit;
|
||||||
import org.springframework.samples.petclinic.visit.VisitRepository;
|
import org.springframework.samples.petclinic.visit.VisitRepository;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
|
@ -44,6 +47,9 @@ class VisitController {
|
||||||
|
|
||||||
private final PetRepository pets;
|
private final PetRepository pets;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ModelMapper modelMapper;
|
||||||
|
|
||||||
public VisitController(VisitRepository visits, PetRepository pets) {
|
public VisitController(VisitRepository visits, PetRepository pets) {
|
||||||
this.visits = visits;
|
this.visits = visits;
|
||||||
this.pets = pets;
|
this.pets = pets;
|
||||||
|
@ -79,7 +85,9 @@ class VisitController {
|
||||||
|
|
||||||
// Spring MVC calls method loadPetWithVisit(...) before processNewVisitForm is called
|
// Spring MVC calls method loadPetWithVisit(...) before processNewVisitForm is called
|
||||||
@PostMapping("/owners/{ownerId}/pets/{petId}/visits/new")
|
@PostMapping("/owners/{ownerId}/pets/{petId}/visits/new")
|
||||||
public String processNewVisitForm(@Valid Visit visit, BindingResult result) {
|
public String processNewVisitForm(@Valid VisitDto visitDto, BindingResult result) {
|
||||||
|
|
||||||
|
Visit visit = modelMapper.map(visitDto, Visit.class);
|
||||||
if (result.hasErrors()) {
|
if (result.hasErrors()) {
|
||||||
return "pets/createOrUpdateVisitForm";
|
return "pets/createOrUpdateVisitForm";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue