diff --git a/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java b/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java index 781184ae2..b12e7c827 100644 --- a/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java @@ -23,7 +23,6 @@ import javax.validation.Valid; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; -import org.springframework.samples.petclinic.visit.VisitRepository; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; @@ -48,11 +47,8 @@ class OwnerController { private final OwnerRepository owners; - private final VisitRepository visits; - - public OwnerController(OwnerRepository clinicService, VisitRepository visits) { + public OwnerController(OwnerRepository clinicService) { this.owners = clinicService; - this.visits = visits; } @InitBinder @@ -161,7 +157,7 @@ class OwnerController { ModelAndView mav = new ModelAndView("owners/ownerDetails"); Owner owner = this.owners.findById(ownerId); for (Pet pet : owner.getPets()) { - pet.setVisitsInternal(visits.findByPetId(pet.getId())); + pet.getVisits(); } mav.addObject(owner); return mav; diff --git a/src/main/java/org/springframework/samples/petclinic/owner/Pet.java b/src/main/java/org/springframework/samples/petclinic/owner/Pet.java index 8b162531c..5aa038eb3 100755 --- a/src/main/java/org/springframework/samples/petclinic/owner/Pet.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/Pet.java @@ -16,23 +16,20 @@ package org.springframework.samples.petclinic.owner; import java.time.LocalDate; -import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; import java.util.LinkedHashSet; -import java.util.List; import java.util.Set; +import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.OrderBy; import javax.persistence.Table; -import javax.persistence.Transient; -import org.springframework.beans.support.MutableSortDefinition; -import org.springframework.beans.support.PropertyComparator; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.samples.petclinic.model.NamedEntity; import org.springframework.samples.petclinic.visit.Visit; @@ -59,7 +56,8 @@ public class Pet extends NamedEntity { @Column private Integer ownerId; - @Transient + @OneToMany(cascade = CascadeType.ALL, mappedBy = "petId", fetch = FetchType.LAZY) + @OrderBy("visit_date ASC") private Set visits = new LinkedHashSet<>(); public void setOwnerId(Integer ownerId) { @@ -82,25 +80,12 @@ public class Pet extends NamedEntity { this.type = type; } - protected Set getVisitsInternal() { - if (this.visits == null) { - this.visits = new HashSet<>(); - } + public Collection getVisits() { return this.visits; } - protected void setVisitsInternal(Collection visits) { - this.visits = new LinkedHashSet<>(visits); - } - - public List getVisits() { - List sortedVisits = new ArrayList<>(getVisitsInternal()); - PropertyComparator.sort(sortedVisits, new MutableSortDefinition("date", false, false)); - return Collections.unmodifiableList(sortedVisits); - } - public void addVisit(Visit visit) { - getVisitsInternal().add(visit); + getVisits().add(visit); visit.setPetId(this.getId()); } diff --git a/src/main/java/org/springframework/samples/petclinic/visit/Visit.java b/src/main/java/org/springframework/samples/petclinic/owner/Visit.java similarity index 96% rename from src/main/java/org/springframework/samples/petclinic/visit/Visit.java rename to src/main/java/org/springframework/samples/petclinic/owner/Visit.java index df9f25fe0..5266f6137 100755 --- a/src/main/java/org/springframework/samples/petclinic/visit/Visit.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/Visit.java @@ -40,10 +40,10 @@ public class Visit extends BaseEntity { private LocalDate date; @NotEmpty - @Column(name = "description") + @Column private String description; - @Column(name = "pet_id") + @Column private Integer petId; /** diff --git a/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java b/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java index d441ffab4..508fde6ee 100644 --- a/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java @@ -15,15 +15,19 @@ */ 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.VisitRepository; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; -import java.util.Map; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.InitBinder; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; /** * @author Juergen Hoeller @@ -35,12 +39,9 @@ import java.util.Map; @Controller class VisitController { - private final VisitRepository visits; - private final OwnerRepository owners; - public VisitController(VisitRepository visits, OwnerRepository owners) { - this.visits = visits; + public VisitController(OwnerRepository owners) { this.owners = owners; } @@ -61,7 +62,6 @@ class VisitController { Map model) { Owner owner = this.owners.findById(ownerId); Pet pet = owner.getPet(petId); - pet.setVisitsInternal(this.visits.findByPetId(petId)); model.put("pet", pet); Visit visit = new Visit(); pet.addVisit(visit); @@ -78,12 +78,14 @@ class VisitController { // Spring MVC calls method loadPetWithVisit(...) before processNewVisitForm is // called @PostMapping("/owners/{ownerId}/pets/{petId}/visits/new") - public String processNewVisitForm(@Valid Visit visit, BindingResult result) { + public String processNewVisitForm(@PathVariable("ownerId") int ownerId, @Valid Visit visit, BindingResult result) { if (result.hasErrors()) { return "pets/createOrUpdateVisitForm"; } else { - this.visits.save(visit); + Owner owner = this.owners.findById(ownerId); + owner.getPet(visit.getPetId()).addVisit(visit); + this.owners.save(owner); return "redirect:/owners/{ownerId}"; } } diff --git a/src/main/java/org/springframework/samples/petclinic/visit/VisitRepository.java b/src/main/java/org/springframework/samples/petclinic/visit/VisitRepository.java deleted file mode 100644 index 4af5079a0..000000000 --- a/src/main/java/org/springframework/samples/petclinic/visit/VisitRepository.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.samples.petclinic.visit; - -import org.springframework.dao.DataAccessException; -import org.springframework.data.repository.Repository; -import org.springframework.samples.petclinic.model.BaseEntity; - -import java.util.List; - -/** - * Repository class for Visit domain objects All method names are compliant - * with Spring Data naming conventions so this interface can easily be extended for Spring - * Data. See: - * https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-creation - * - * @author Ken Krebs - * @author Juergen Hoeller - * @author Sam Brannen - * @author Michael Isvy - */ -public interface VisitRepository extends Repository { - - /** - * Save a Visit to the data store, either inserting or updating it. - * @param visit the Visit to save - * @see BaseEntity#isNew - */ - void save(Visit visit) throws DataAccessException; - - List findByPetId(Integer petId); - -} diff --git a/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java b/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java index adeaeacbe..def9efbc1 100644 --- a/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java +++ b/src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.java @@ -47,7 +47,6 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.samples.petclinic.visit.Visit; -import org.springframework.samples.petclinic.visit.VisitRepository; import org.springframework.test.web.servlet.MockMvc; /** @@ -66,9 +65,6 @@ class OwnerControllerTests { @MockBean private OwnerRepository owners; - @MockBean - private VisitRepository visits; - private Owner george() { Owner george = new Owner(); george.setId(TEST_OWNER_ID); @@ -91,15 +87,17 @@ class OwnerControllerTests { @BeforeEach void setup() { + Owner george = george(); given(this.owners.findByLastName(eq("Franklin"), any(Pageable.class))) - .willReturn(new PageImpl(Lists.newArrayList(george()))); + .willReturn(new PageImpl(Lists.newArrayList(george))); - given(this.owners.findAll(any(Pageable.class))).willReturn(new PageImpl(Lists.newArrayList(george()))); + given(this.owners.findAll(any(Pageable.class))).willReturn(new PageImpl(Lists.newArrayList(george))); - 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(george().getPet("Max").getId())).willReturn(Collections.singletonList(visit)); + visit.setPetId(george.getPet("Max").getId()); + george.getPet("Max").getVisits().add(visit); } diff --git a/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java b/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java index d331f3bc3..1ecf045f3 100644 --- a/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java +++ b/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.java @@ -16,19 +16,20 @@ package org.springframework.samples.petclinic.owner; +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.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; 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.VisitRepository; import org.springframework.test.web.servlet.MockMvc; -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.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; - /** * Test class for {@link VisitController} * @@ -44,9 +45,6 @@ class VisitControllerTests { @Autowired private MockMvc mockMvc; - @MockBean - private VisitRepository visits; - @MockBean private OwnerRepository owners; diff --git a/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java b/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java index 83b353bb9..236cd19a9 100644 --- a/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java +++ b/src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.java @@ -36,7 +36,6 @@ import org.springframework.samples.petclinic.owner.PetType; import org.springframework.samples.petclinic.vet.Vet; import org.springframework.samples.petclinic.vet.VetRepository; import org.springframework.samples.petclinic.visit.Visit; -import org.springframework.samples.petclinic.visit.VisitRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -76,9 +75,6 @@ class ClinicServiceTests { @Autowired protected OwnerRepository owners; - @Autowired - protected VisitRepository visits; - @Autowired protected VetRepository vets; @@ -205,17 +201,18 @@ class ClinicServiceTests { Visit visit = new Visit(); pet7.addVisit(visit); visit.setDescription("test"); - this.visits.save(visit); this.owners.save(owner6); owner6 = this.owners.findById(6); assertThat(pet7.getVisits().size()).isEqualTo(found + 1); - assertThat(visit.getId()).isNotNull(); + assertThat(pet7.getVisits()).allMatch(value -> value.getId() != null); } @Test void shouldFindVisitsByPetId() throws Exception { - Collection visits = this.visits.findByPetId(7); + Owner owner6 = this.owners.findById(6); + Pet pet7 = owner6.getPet(7); + Collection visits = pet7.getVisits(); assertThat(visits).hasSize(2); Visit[] visitArr = visits.toArray(new Visit[visits.size()]); assertThat(visitArr[0].getDate()).isNotNull();