Also remove VisitRepository

Rely on Hibernate to do lazy loading on visits.
This commit is contained in:
Dave Syer 2022-01-05 08:55:24 +00:00 committed by Dave Syer
parent a5da14ae2f
commit 58fe6298f8
8 changed files with 43 additions and 113 deletions

View file

@ -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;

View file

@ -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<Visit> visits = new LinkedHashSet<>();
public void setOwnerId(Integer ownerId) {
@ -82,25 +80,12 @@ public class Pet extends NamedEntity {
this.type = type;
}
protected Set<Visit> getVisitsInternal() {
if (this.visits == null) {
this.visits = new HashSet<>();
}
public Collection<Visit> getVisits() {
return this.visits;
}
protected void setVisitsInternal(Collection<Visit> visits) {
this.visits = new LinkedHashSet<>(visits);
}
public List<Visit> getVisits() {
List<Visit> 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());
}

View file

@ -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;
/**

View file

@ -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<String, Object> 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}";
}
}

View file

@ -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 <code>Visit</code> 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<Visit, Integer> {
/**
* Save a <code>Visit</code> to the data store, either inserting or updating it.
* @param visit the <code>Visit</code> to save
* @see BaseEntity#isNew
*/
void save(Visit visit) throws DataAccessException;
List<Visit> findByPetId(Integer petId);
}

View file

@ -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<Owner>(Lists.newArrayList(george())));
.willReturn(new PageImpl<Owner>(Lists.newArrayList(george)));
given(this.owners.findAll(any(Pageable.class))).willReturn(new PageImpl<Owner>(Lists.newArrayList(george())));
given(this.owners.findAll(any(Pageable.class))).willReturn(new PageImpl<Owner>(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);
}

View file

@ -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;

View file

@ -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<Visit> visits = this.visits.findByPetId(7);
Owner owner6 = this.owners.findById(6);
Pet pet7 = owner6.getPet(7);
Collection<Visit> visits = pet7.getVisits();
assertThat(visits).hasSize(2);
Visit[] visitArr = visits.toArray(new Visit[visits.size()]);
assertThat(visitArr[0].getDate()).isNotNull();