mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-07-15 20:25:50 +00:00
Make Pet.visits @Transient
In that way the Pet and Visit entities are more modular, and we don't have to rely on a bit of a hack which is that Hibernate happily maps Pet to its ID in the entity generation (but fails if you do it at compile time).
This commit is contained in:
parent
d6bdc13bdb
commit
7ef045dac8
4 changed files with 77 additions and 25 deletions
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.samples.petclinic.owner;
|
package org.springframework.samples.petclinic.owner;
|
||||||
|
|
||||||
|
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;
|
||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
|
@ -40,10 +41,12 @@ class OwnerController {
|
||||||
|
|
||||||
private static final String VIEWS_OWNER_CREATE_OR_UPDATE_FORM = "owners/createOrUpdateOwnerForm";
|
private static final String VIEWS_OWNER_CREATE_OR_UPDATE_FORM = "owners/createOrUpdateOwnerForm";
|
||||||
private final OwnerRepository owners;
|
private final OwnerRepository owners;
|
||||||
|
private VisitRepository visits;
|
||||||
|
|
||||||
|
|
||||||
public OwnerController(OwnerRepository clinicService) {
|
public OwnerController(OwnerRepository clinicService, VisitRepository visits) {
|
||||||
this.owners = clinicService;
|
this.owners = clinicService;
|
||||||
|
this.visits = visits;
|
||||||
}
|
}
|
||||||
|
|
||||||
@InitBinder
|
@InitBinder
|
||||||
|
@ -126,7 +129,11 @@ class OwnerController {
|
||||||
@GetMapping("/owners/{ownerId}")
|
@GetMapping("/owners/{ownerId}")
|
||||||
public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) {
|
public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) {
|
||||||
ModelAndView mav = new ModelAndView("owners/ownerDetails");
|
ModelAndView mav = new ModelAndView("owners/ownerDetails");
|
||||||
mav.addObject(this.owners.findById(ownerId));
|
Owner owner = this.owners.findById(ownerId);
|
||||||
|
for (Pet pet : owner.getPets()) {
|
||||||
|
pet.setVisitsInternal(visits.findByPetId(pet.getId()));
|
||||||
|
}
|
||||||
|
mav.addObject(owner);
|
||||||
return mav;
|
return mav;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,20 +17,19 @@ package org.springframework.samples.petclinic.owner;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.persistence.CascadeType;
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.FetchType;
|
|
||||||
import javax.persistence.JoinColumn;
|
import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.OneToMany;
|
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.Transient;
|
||||||
|
|
||||||
import org.springframework.beans.support.MutableSortDefinition;
|
import org.springframework.beans.support.MutableSortDefinition;
|
||||||
import org.springframework.beans.support.PropertyComparator;
|
import org.springframework.beans.support.PropertyComparator;
|
||||||
|
@ -61,7 +60,7 @@ public class Pet extends NamedEntity {
|
||||||
@JoinColumn(name = "owner_id")
|
@JoinColumn(name = "owner_id")
|
||||||
private Owner owner;
|
private Owner owner;
|
||||||
|
|
||||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "petId", fetch = FetchType.EAGER)
|
@Transient
|
||||||
private Set<Visit> visits = new LinkedHashSet<>();
|
private Set<Visit> visits = new LinkedHashSet<>();
|
||||||
|
|
||||||
public void setBirthDate(LocalDate birthDate) {
|
public void setBirthDate(LocalDate birthDate) {
|
||||||
|
@ -95,8 +94,8 @@ public class Pet extends NamedEntity {
|
||||||
return this.visits;
|
return this.visits;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setVisitsInternal(Set<Visit> visits) {
|
protected void setVisitsInternal(Collection<Visit> visits) {
|
||||||
this.visits = visits;
|
this.visits = new LinkedHashSet<>(visits);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Visit> getVisits() {
|
public List<Visit> getVisits() {
|
||||||
|
|
|
@ -15,15 +15,20 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.samples.petclinic.owner;
|
package org.springframework.samples.petclinic.owner;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
|
||||||
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;
|
||||||
import org.springframework.validation.BindingResult;
|
import org.springframework.validation.BindingResult;
|
||||||
import org.springframework.web.bind.WebDataBinder;
|
import org.springframework.web.bind.WebDataBinder;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.InitBinder;
|
||||||
import javax.validation.Valid;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import java.util.Map;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
@ -62,6 +67,7 @@ class VisitController {
|
||||||
@ModelAttribute("visit")
|
@ModelAttribute("visit")
|
||||||
public Visit loadPetWithVisit(@PathVariable("petId") int petId, Map<String, Object> model) {
|
public Visit loadPetWithVisit(@PathVariable("petId") int petId, Map<String, Object> model) {
|
||||||
Pet pet = this.pets.findById(petId);
|
Pet pet = this.pets.findById(petId);
|
||||||
|
pet.setVisitsInternal(this.visits.findByPetId(petId));
|
||||||
model.put("pet", pet);
|
model.put("pet", pet);
|
||||||
Visit visit = new Visit();
|
Visit visit = new Visit();
|
||||||
pet.addVisit(visit);
|
pet.addVisit(visit);
|
||||||
|
|
|
@ -16,8 +16,29 @@
|
||||||
|
|
||||||
package org.springframework.samples.petclinic.owner;
|
package org.springframework.samples.petclinic.owner;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.assertj.core.util.Lists;
|
||||||
|
import org.hamcrest.BaseMatcher;
|
||||||
|
import org.hamcrest.Description;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||||
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
|
import org.springframework.samples.petclinic.visit.Visit;
|
||||||
|
import org.springframework.samples.petclinic.visit.VisitRepository;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
import static org.hamcrest.Matchers.hasProperty;
|
import static org.hamcrest.Matchers.hasProperty;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
|
@ -25,19 +46,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
|
||||||
|
|
||||||
import org.assertj.core.util.Lists;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
|
||||||
import org.springframework.samples.petclinic.owner.Owner;
|
|
||||||
import org.springframework.samples.petclinic.owner.OwnerController;
|
|
||||||
import org.springframework.samples.petclinic.owner.OwnerRepository;
|
|
||||||
import org.springframework.test.context.junit4.SpringRunner;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test class for {@link OwnerController}
|
* Test class for {@link OwnerController}
|
||||||
*
|
*
|
||||||
|
@ -55,6 +63,9 @@ public class OwnerControllerTests {
|
||||||
@MockBean
|
@MockBean
|
||||||
private OwnerRepository owners;
|
private OwnerRepository owners;
|
||||||
|
|
||||||
|
@MockBean
|
||||||
|
private VisitRepository visits;
|
||||||
|
|
||||||
private Owner george;
|
private Owner george;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -66,7 +77,18 @@ public class OwnerControllerTests {
|
||||||
george.setAddress("110 W. Liberty St.");
|
george.setAddress("110 W. Liberty St.");
|
||||||
george.setCity("Madison");
|
george.setCity("Madison");
|
||||||
george.setTelephone("6085551023");
|
george.setTelephone("6085551023");
|
||||||
|
Pet max = new Pet();
|
||||||
|
PetType dog = new PetType();
|
||||||
|
dog.setName("dog");
|
||||||
|
max.setId(1);
|
||||||
|
max.setType(dog);
|
||||||
|
max.setName("Max");
|
||||||
|
max.setBirthDate(LocalDate.now());
|
||||||
|
george.setPetsInternal(Collections.singleton(max));
|
||||||
given(this.owners.findById(TEST_OWNER_ID)).willReturn(george);
|
given(this.owners.findById(TEST_OWNER_ID)).willReturn(george);
|
||||||
|
Visit visit = new Visit();
|
||||||
|
visit.setDate(LocalDate.now());
|
||||||
|
given(this.visits.findByPetId(max.getId())).willReturn(Collections.singletonList(visit));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -189,6 +211,24 @@ public class OwnerControllerTests {
|
||||||
.andExpect(model().attribute("owner", hasProperty("address", is("110 W. Liberty St."))))
|
.andExpect(model().attribute("owner", hasProperty("address", is("110 W. Liberty St."))))
|
||||||
.andExpect(model().attribute("owner", hasProperty("city", is("Madison"))))
|
.andExpect(model().attribute("owner", hasProperty("city", is("Madison"))))
|
||||||
.andExpect(model().attribute("owner", hasProperty("telephone", is("6085551023"))))
|
.andExpect(model().attribute("owner", hasProperty("telephone", is("6085551023"))))
|
||||||
|
.andExpect(model().attribute("owner", hasProperty("pets", not(empty()))))
|
||||||
|
.andExpect(model().attribute("owner", hasProperty("pets", new BaseMatcher<List<Pet>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(Object item) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Pet> pets = (List<Pet>) item;
|
||||||
|
Pet pet = pets.get(0);
|
||||||
|
if (pet.getVisits().isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void describeTo(Description description) {
|
||||||
|
description.appendText("Max did not have any visits");
|
||||||
|
}})))
|
||||||
.andExpect(view().name("owners/ownerDetails"));
|
.andExpect(view().name("owners/ownerDetails"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue