mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-04-26 20:32:48 +00:00
Also remove VisitRepository
Rely on Hibernate to do lazy loading on visits.
This commit is contained in:
parent
a5da14ae2f
commit
58fe6298f8
8 changed files with 43 additions and 113 deletions
|
@ -23,7 +23,6 @@ import javax.validation.Valid;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
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;
|
||||||
|
@ -48,11 +47,8 @@ class OwnerController {
|
||||||
|
|
||||||
private final OwnerRepository owners;
|
private final OwnerRepository owners;
|
||||||
|
|
||||||
private final VisitRepository visits;
|
public OwnerController(OwnerRepository clinicService) {
|
||||||
|
|
||||||
public OwnerController(OwnerRepository clinicService, VisitRepository visits) {
|
|
||||||
this.owners = clinicService;
|
this.owners = clinicService;
|
||||||
this.visits = visits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InitBinder
|
@InitBinder
|
||||||
|
@ -161,7 +157,7 @@ class OwnerController {
|
||||||
ModelAndView mav = new ModelAndView("owners/ownerDetails");
|
ModelAndView mav = new ModelAndView("owners/ownerDetails");
|
||||||
Owner owner = this.owners.findById(ownerId);
|
Owner owner = this.owners.findById(ownerId);
|
||||||
for (Pet pet : owner.getPets()) {
|
for (Pet pet : owner.getPets()) {
|
||||||
pet.setVisitsInternal(visits.findByPetId(pet.getId()));
|
pet.getVisits();
|
||||||
}
|
}
|
||||||
mav.addObject(owner);
|
mav.addObject(owner);
|
||||||
return mav;
|
return mav;
|
||||||
|
|
|
@ -16,23 +16,20 @@
|
||||||
package org.springframework.samples.petclinic.owner;
|
package org.springframework.samples.petclinic.owner;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
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.OrderBy;
|
||||||
import javax.persistence.Table;
|
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.format.annotation.DateTimeFormat;
|
||||||
import org.springframework.samples.petclinic.model.NamedEntity;
|
import org.springframework.samples.petclinic.model.NamedEntity;
|
||||||
import org.springframework.samples.petclinic.visit.Visit;
|
import org.springframework.samples.petclinic.visit.Visit;
|
||||||
|
@ -59,7 +56,8 @@ public class Pet extends NamedEntity {
|
||||||
@Column
|
@Column
|
||||||
private Integer ownerId;
|
private Integer ownerId;
|
||||||
|
|
||||||
@Transient
|
@OneToMany(cascade = CascadeType.ALL, mappedBy = "petId", fetch = FetchType.LAZY)
|
||||||
|
@OrderBy("visit_date ASC")
|
||||||
private Set<Visit> visits = new LinkedHashSet<>();
|
private Set<Visit> visits = new LinkedHashSet<>();
|
||||||
|
|
||||||
public void setOwnerId(Integer ownerId) {
|
public void setOwnerId(Integer ownerId) {
|
||||||
|
@ -82,25 +80,12 @@ public class Pet extends NamedEntity {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Set<Visit> getVisitsInternal() {
|
public Collection<Visit> getVisits() {
|
||||||
if (this.visits == null) {
|
|
||||||
this.visits = new HashSet<>();
|
|
||||||
}
|
|
||||||
return this.visits;
|
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) {
|
public void addVisit(Visit visit) {
|
||||||
getVisitsInternal().add(visit);
|
getVisits().add(visit);
|
||||||
visit.setPetId(this.getId());
|
visit.setPetId(this.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,10 +40,10 @@ public class Visit extends BaseEntity {
|
||||||
private LocalDate date;
|
private LocalDate date;
|
||||||
|
|
||||||
@NotEmpty
|
@NotEmpty
|
||||||
@Column(name = "description")
|
@Column
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
@Column(name = "pet_id")
|
@Column
|
||||||
private Integer petId;
|
private Integer petId;
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -15,15 +15,19 @@
|
||||||
*/
|
*/
|
||||||
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.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
|
||||||
|
@ -35,12 +39,9 @@ import java.util.Map;
|
||||||
@Controller
|
@Controller
|
||||||
class VisitController {
|
class VisitController {
|
||||||
|
|
||||||
private final VisitRepository visits;
|
|
||||||
|
|
||||||
private final OwnerRepository owners;
|
private final OwnerRepository owners;
|
||||||
|
|
||||||
public VisitController(VisitRepository visits, OwnerRepository owners) {
|
public VisitController(OwnerRepository owners) {
|
||||||
this.visits = visits;
|
|
||||||
this.owners = owners;
|
this.owners = owners;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +62,6 @@ class VisitController {
|
||||||
Map<String, Object> model) {
|
Map<String, Object> model) {
|
||||||
Owner owner = this.owners.findById(ownerId);
|
Owner owner = this.owners.findById(ownerId);
|
||||||
Pet pet = owner.getPet(petId);
|
Pet pet = owner.getPet(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);
|
||||||
|
@ -78,12 +78,14 @@ class VisitController {
|
||||||
// Spring MVC calls method loadPetWithVisit(...) before processNewVisitForm is
|
// Spring MVC calls method loadPetWithVisit(...) before processNewVisitForm is
|
||||||
// called
|
// 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(@PathVariable("ownerId") int ownerId, @Valid Visit visit, BindingResult result) {
|
||||||
if (result.hasErrors()) {
|
if (result.hasErrors()) {
|
||||||
return "pets/createOrUpdateVisitForm";
|
return "pets/createOrUpdateVisitForm";
|
||||||
}
|
}
|
||||||
else {
|
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}";
|
return "redirect:/owners/{ownerId}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
|
|
||||||
}
|
|
|
@ -47,7 +47,6 @@ import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageImpl;
|
import org.springframework.data.domain.PageImpl;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.samples.petclinic.visit.Visit;
|
import org.springframework.samples.petclinic.visit.Visit;
|
||||||
import org.springframework.samples.petclinic.visit.VisitRepository;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,9 +65,6 @@ class OwnerControllerTests {
|
||||||
@MockBean
|
@MockBean
|
||||||
private OwnerRepository owners;
|
private OwnerRepository owners;
|
||||||
|
|
||||||
@MockBean
|
|
||||||
private VisitRepository visits;
|
|
||||||
|
|
||||||
private Owner george() {
|
private Owner george() {
|
||||||
Owner george = new Owner();
|
Owner george = new Owner();
|
||||||
george.setId(TEST_OWNER_ID);
|
george.setId(TEST_OWNER_ID);
|
||||||
|
@ -91,15 +87,17 @@ class OwnerControllerTests {
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setup() {
|
void setup() {
|
||||||
|
|
||||||
|
Owner george = george();
|
||||||
given(this.owners.findByLastName(eq("Franklin"), any(Pageable.class)))
|
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 visit = new Visit();
|
||||||
visit.setDate(LocalDate.now());
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,19 +16,20 @@
|
||||||
|
|
||||||
package org.springframework.samples.petclinic.owner;
|
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.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
import org.springframework.samples.petclinic.visit.VisitRepository;
|
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
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}
|
* Test class for {@link VisitController}
|
||||||
*
|
*
|
||||||
|
@ -44,9 +45,6 @@ class VisitControllerTests {
|
||||||
@Autowired
|
@Autowired
|
||||||
private MockMvc mockMvc;
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
@MockBean
|
|
||||||
private VisitRepository visits;
|
|
||||||
|
|
||||||
@MockBean
|
@MockBean
|
||||||
private OwnerRepository owners;
|
private OwnerRepository owners;
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,6 @@ import org.springframework.samples.petclinic.owner.PetType;
|
||||||
import org.springframework.samples.petclinic.vet.Vet;
|
import org.springframework.samples.petclinic.vet.Vet;
|
||||||
import org.springframework.samples.petclinic.vet.VetRepository;
|
import org.springframework.samples.petclinic.vet.VetRepository;
|
||||||
import org.springframework.samples.petclinic.visit.Visit;
|
import org.springframework.samples.petclinic.visit.Visit;
|
||||||
import org.springframework.samples.petclinic.visit.VisitRepository;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@ -76,9 +75,6 @@ class ClinicServiceTests {
|
||||||
@Autowired
|
@Autowired
|
||||||
protected OwnerRepository owners;
|
protected OwnerRepository owners;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
protected VisitRepository visits;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
protected VetRepository vets;
|
protected VetRepository vets;
|
||||||
|
|
||||||
|
@ -205,17 +201,18 @@ class ClinicServiceTests {
|
||||||
Visit visit = new Visit();
|
Visit visit = new Visit();
|
||||||
pet7.addVisit(visit);
|
pet7.addVisit(visit);
|
||||||
visit.setDescription("test");
|
visit.setDescription("test");
|
||||||
this.visits.save(visit);
|
|
||||||
this.owners.save(owner6);
|
this.owners.save(owner6);
|
||||||
|
|
||||||
owner6 = this.owners.findById(6);
|
owner6 = this.owners.findById(6);
|
||||||
assertThat(pet7.getVisits().size()).isEqualTo(found + 1);
|
assertThat(pet7.getVisits().size()).isEqualTo(found + 1);
|
||||||
assertThat(visit.getId()).isNotNull();
|
assertThat(pet7.getVisits()).allMatch(value -> value.getId() != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldFindVisitsByPetId() throws Exception {
|
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);
|
assertThat(visits).hasSize(2);
|
||||||
Visit[] visitArr = visits.toArray(new Visit[visits.size()]);
|
Visit[] visitArr = visits.toArray(new Visit[visits.size()]);
|
||||||
assertThat(visitArr[0].getDate()).isNotNull();
|
assertThat(visitArr[0].getDate()).isNotNull();
|
||||||
|
|
Loading…
Reference in a new issue