Modularize and migrate to aggregate-oriented domain

Vet, Owner, Visit. The Visit "aggregate" is a little artificial
but it demonstrates a useful point about not holding on to
references of "parent" (reference data) objects, i.e. the Visit has
an Integer petId, instead of a Pet field. In principle this app is
now almost ready to migrate to multiple services if anyone wanted
to do that.
This commit is contained in:
Dave Syer 2016-11-10 22:10:56 +00:00
parent 8c8599298a
commit 83ff9a50e3
34 changed files with 270 additions and 384 deletions

View file

@ -21,6 +21,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* PetClinic Spring Boot Application.
*
* @author Dave Syer
*
*/
@SpringBootApplication

View file

@ -1,5 +1,5 @@
/**
* The classes in this package represent PetClinic's business layer.
*/
package org.springframework.samples.petclinic.model;
/**
* The classes in this package represent utilities used by the domain.
*/
package org.springframework.samples.petclinic.model;

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
package org.springframework.samples.petclinic.owner;
import java.util.ArrayList;
import java.util.Collections;
@ -32,6 +32,7 @@ import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.beans.support.MutableSortDefinition;
import org.springframework.beans.support.PropertyComparator;
import org.springframework.core.style.ToStringCreator;
import org.springframework.samples.petclinic.model.Person;
/**
* Simple JavaBean domain object representing an owner.

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.web;
package org.springframework.samples.petclinic.owner;
import java.util.Collection;
import java.util.Map;
@ -21,8 +21,6 @@ import java.util.Map;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.samples.petclinic.model.Owner;
import org.springframework.samples.petclinic.service.ClinicService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
@ -40,15 +38,15 @@ import org.springframework.web.servlet.ModelAndView;
* @author Michael Isvy
*/
@Controller
public class OwnerController {
class OwnerController {
private static final String VIEWS_OWNER_CREATE_OR_UPDATE_FORM = "owners/createOrUpdateOwnerForm";
private final ClinicService clinicService;
private final OwnerRepository owners;
@Autowired
public OwnerController(ClinicService clinicService) {
this.clinicService = clinicService;
public OwnerController(OwnerRepository clinicService) {
this.owners = clinicService;
}
@InitBinder
@ -68,7 +66,7 @@ public class OwnerController {
if (result.hasErrors()) {
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
} else {
this.clinicService.saveOwner(owner);
this.owners.save(owner);
return "redirect:/owners/" + owner.getId();
}
}
@ -88,7 +86,7 @@ public class OwnerController {
}
// find owners by last name
Collection<Owner> results = this.clinicService.findOwnerByLastName(owner.getLastName());
Collection<Owner> results = this.owners.findByLastName(owner.getLastName());
if (results.isEmpty()) {
// no owners found
result.rejectValue("lastName", "notFound", "not found");
@ -106,7 +104,7 @@ public class OwnerController {
@RequestMapping(value = "/owners/{ownerId}/edit", method = RequestMethod.GET)
public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) {
Owner owner = this.clinicService.findOwnerById(ownerId);
Owner owner = this.owners.findById(ownerId);
model.addAttribute(owner);
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
}
@ -117,7 +115,7 @@ public class OwnerController {
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
} else {
owner.setId(ownerId);
this.clinicService.saveOwner(owner);
this.owners.save(owner);
return "redirect:/owners/{ownerId}";
}
}
@ -131,7 +129,7 @@ public class OwnerController {
@RequestMapping("/owners/{ownerId}")
public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) {
ModelAndView mav = new ModelAndView("owners/ownerDetails");
mav.addObject(this.clinicService.findOwnerById(ownerId));
mav.addObject(this.owners.findById(ownerId));
return mav;
}

View file

@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository;
package org.springframework.samples.petclinic.owner;
import java.util.Collection;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.query.Param;
import org.springframework.samples.petclinic.model.Owner;
import org.springframework.transaction.annotation.Transactional;
/**
* Repository class for <code>Owner</code> domain objects All method names are compliant with Spring Data naming
@ -41,6 +41,7 @@ public interface OwnerRepository extends Repository<Owner, Integer> {
* found)
*/
@Query("SELECT DISTINCT owner FROM Owner owner left join fetch owner.pets WHERE owner.lastName LIKE :lastName%")
@Transactional(readOnly = true)
Collection<Owner> findByLastName(@Param("lastName") String lastName);
/**
@ -49,6 +50,7 @@ public interface OwnerRepository extends Repository<Owner, Integer> {
* @return the {@link Owner} if found
*/
@Query("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:id")
@Transactional(readOnly = true)
Owner findById(@Param("id") Integer id);
/**

View file

@ -13,11 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
package org.springframework.samples.petclinic.owner;
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;
import javax.persistence.CascadeType;
import javax.persistence.Column;
@ -62,10 +64,9 @@ public class Pet extends NamedEntity {
@JoinColumn(name = "owner_id")
private Owner owner;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "pet", fetch = FetchType.EAGER)
@OneToMany(cascade = CascadeType.ALL, mappedBy="petId", fetch = FetchType.EAGER)
private Set<Visit> visits = new LinkedHashSet<>();
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
@ -109,11 +110,7 @@ public class Pet extends NamedEntity {
public void addVisit(Visit visit) {
getVisitsInternal().add(visit);
visit.setPet(this);
visit.setPetId(this.id);
}
}

View file

@ -13,23 +13,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.web;
package org.springframework.samples.petclinic.owner;
import java.util.Collection;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.samples.petclinic.model.Owner;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.samples.petclinic.service.ClinicService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Collection;
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.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* @author Juergen Hoeller
@ -38,24 +38,26 @@ import java.util.Collection;
*/
@Controller
@RequestMapping("/owners/{ownerId}")
public class PetController {
class PetController {
private static final String VIEWS_PETS_CREATE_OR_UPDATE_FORM = "pets/createOrUpdatePetForm";
private final ClinicService clinicService;
private final PetRepository pets;
private final OwnerRepository owners;
@Autowired
public PetController(ClinicService clinicService) {
this.clinicService = clinicService;
public PetController(PetRepository pets, OwnerRepository owners) {
this.pets = pets;
this.owners = owners;
}
@ModelAttribute("types")
public Collection<PetType> populatePetTypes() {
return this.clinicService.findPetTypes();
return this.pets.findPetTypes();
}
@ModelAttribute("owner")
public Owner findOwner(@PathVariable("ownerId") int ownerId) {
return this.clinicService.findOwnerById(ownerId);
return this.owners.findById(ownerId);
}
@InitBinder("owner")
@ -86,14 +88,14 @@ public class PetController {
return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
} else {
owner.addPet(pet);
this.clinicService.savePet(pet);
this.pets.save(pet);
return "redirect:/owners/{ownerId}";
}
}
@RequestMapping(value = "/pets/{petId}/edit", method = RequestMethod.GET)
public String initUpdateForm(@PathVariable("petId") int petId, ModelMap model) {
Pet pet = this.clinicService.findPetById(petId);
Pet pet = this.pets.findById(petId);
model.put("pet", pet);
return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
}
@ -105,7 +107,7 @@ public class PetController {
return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
} else {
owner.addPet(pet);
this.clinicService.savePet(pet);
this.pets.save(pet);
return "redirect:/owners/{ownerId}";
}
}

View file

@ -13,14 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository;
package org.springframework.samples.petclinic.owner;
import java.util.List;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.transaction.annotation.Transactional;
/**
* Repository class for <code>Pet</code> domain objects All method names are compliant with Spring Data naming
@ -38,6 +37,7 @@ public interface PetRepository extends Repository<Pet, Integer> {
* @return a Collection of {@link PetType}s.
*/
@Query("SELECT ptype FROM PetType ptype ORDER BY ptype.name")
@Transactional(readOnly = true)
List<PetType> findPetTypes();
/**
@ -45,6 +45,7 @@ public interface PetRepository extends Repository<Pet, Integer> {
* @param id the id to search for
* @return the {@link Pet} if found
*/
@Transactional(readOnly = true)
Pet findById(Integer id);
/**

View file

@ -13,11 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
package org.springframework.samples.petclinic.owner;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.springframework.samples.petclinic.model.NamedEntity;
/**
* @author Juergen Hoeller
* Can be Cat, Dog, Hamster...

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.web;
package org.springframework.samples.petclinic.owner;
import java.text.ParseException;
@ -22,8 +22,6 @@ import java.util.Locale;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.Formatter;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.samples.petclinic.service.ClinicService;
import org.springframework.stereotype.Component;
/**
@ -32,7 +30,6 @@ import org.springframework.stereotype.Component;
* Spring ref doc: http://static.springsource.org/spring/docs/current/spring-framework-reference/html/validation.html#format-Formatter-SPI
* - A nice blog entry from Gordon Dickens: http://gordondickens.com/wordpress/2010/09/30/using-spring-3-0-custom-type-converter/
* <p/>
* Also see how the bean 'conversionService' has been declared inside /WEB-INF/mvc-core-config.xml
*
* @author Mark Fisher
* @author Juergen Hoeller
@ -41,12 +38,12 @@ import org.springframework.stereotype.Component;
@Component
public class PetTypeFormatter implements Formatter<PetType> {
private final ClinicService clinicService;
private final PetRepository pets;
@Autowired
public PetTypeFormatter(ClinicService clinicService) {
this.clinicService = clinicService;
public PetTypeFormatter(PetRepository pets) {
this.pets = pets;
}
@Override
@ -56,7 +53,7 @@ public class PetTypeFormatter implements Formatter<PetType> {
@Override
public PetType parse(String text, Locale locale) throws ParseException {
Collection<PetType> findPetTypes = this.clinicService.findPetTypes();
Collection<PetType> findPetTypes = this.pets.findPetTypes();
for (PetType type : findPetTypes) {
if (type.getName().equals(text)) {
return type;

View file

@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.web;
package org.springframework.samples.petclinic.owner;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

View file

@ -13,16 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.web;
package org.springframework.samples.petclinic.owner;
import java.util.Map;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.model.Visit;
import org.springframework.samples.petclinic.service.ClinicService;
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;
@ -37,16 +36,19 @@ import org.springframework.web.bind.annotation.RequestMethod;
* @author Ken Krebs
* @author Arjen Poutsma
* @author Michael Isvy
* @author Dave Syer
*/
@Controller
public class VisitController {
class VisitController {
private final ClinicService clinicService;
private final VisitRepository visits;
private final PetRepository pets;
@Autowired
public VisitController(ClinicService clinicService) {
this.clinicService = clinicService;
public VisitController(VisitRepository visits, PetRepository pets) {
this.visits = visits;
this.pets = pets;
}
@InitBinder
@ -65,8 +67,9 @@ public class VisitController {
* @return Pet
*/
@ModelAttribute("visit")
public Visit loadPetWithVisit(@PathVariable("petId") int petId) {
Pet pet = this.clinicService.findPetById(petId);
public Visit loadPetWithVisit(@PathVariable("petId") int petId, Map<String, Object> model) {
Pet pet = this.pets.findById(petId);
model.put("pet", pet);
Visit visit = new Visit();
pet.addVisit(visit);
return visit;
@ -84,7 +87,7 @@ public class VisitController {
if (result.hasErrors()) {
return "pets/createOrUpdateVisitForm";
} else {
this.clinicService.saveVisit(visit);
this.visits.save(visit);
return "redirect:/owners/{ownerId}";
}
}

View file

@ -1,53 +0,0 @@
/*
* Copyright 2002-2013 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
*
* http://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.service;
import java.util.Collection;
import org.springframework.dao.DataAccessException;
import org.springframework.samples.petclinic.model.Owner;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.samples.petclinic.model.Vet;
import org.springframework.samples.petclinic.model.Visit;
/**
* Mostly used as a facade so all controllers have a single point of entry
*
* @author Michael Isvy
*/
public interface ClinicService {
Collection<PetType> findPetTypes() throws DataAccessException;
Owner findOwnerById(int id) throws DataAccessException;
Pet findPetById(int id) throws DataAccessException;
void savePet(Pet pet) throws DataAccessException;
void saveVisit(Visit visit) throws DataAccessException;
Collection<Vet> findVets() throws DataAccessException;
void saveOwner(Owner owner) throws DataAccessException;
Collection<Owner> findOwnerByLastName(String lastName) throws DataAccessException;
Collection<Visit> findVisitsByPetId(int petId);
}

View file

@ -1,108 +0,0 @@
/*
* Copyright 2002-2013 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
*
* http://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.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.samples.petclinic.model.*;
import org.springframework.samples.petclinic.repository.OwnerRepository;
import org.springframework.samples.petclinic.repository.PetRepository;
import org.springframework.samples.petclinic.repository.VetRepository;
import org.springframework.samples.petclinic.repository.VisitRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.cache.annotation.CacheResult;
import java.util.Collection;
/**
* Mostly used as a facade for all Petclinic controllers Also a placeholder
* for @Transactional and @CacheResult annotations
*
* @author Michael Isvy
*/
@Service
public class ClinicServiceImpl implements ClinicService {
private PetRepository petRepository;
private VetRepository vetRepository;
private OwnerRepository ownerRepository;
private VisitRepository visitRepository;
@Autowired
public ClinicServiceImpl(PetRepository petRepository, VetRepository vetRepository, OwnerRepository ownerRepository,
VisitRepository visitRepository) {
this.petRepository = petRepository;
this.vetRepository = vetRepository;
this.ownerRepository = ownerRepository;
this.visitRepository = visitRepository;
}
@Override
@Transactional(readOnly = true)
public Collection<PetType> findPetTypes() throws DataAccessException {
return petRepository.findPetTypes();
}
@Override
@Transactional(readOnly = true)
public Owner findOwnerById(int id) throws DataAccessException {
return ownerRepository.findById(id);
}
@Override
@Transactional(readOnly = true)
public Collection<Owner> findOwnerByLastName(String lastName) throws DataAccessException {
return ownerRepository.findByLastName(lastName);
}
@Override
@Transactional
public void saveOwner(Owner owner) throws DataAccessException {
ownerRepository.save(owner);
}
@Override
@Transactional
public void saveVisit(Visit visit) throws DataAccessException {
visitRepository.save(visit);
}
@Override
@Transactional(readOnly = true)
public Pet findPetById(int id) throws DataAccessException {
return petRepository.findById(id);
}
@Override
@Transactional
public void savePet(Pet pet) throws DataAccessException {
petRepository.save(pet);
}
@Override
@Transactional(readOnly = true)
@CacheResult(cacheName = "vets")
public Collection<Vet> findVets() throws DataAccessException {
return vetRepository.findAll();
}
@Override
public Collection<Visit> findVisitsByPetId(int petId) {
return visitRepository.findByPetId(petId);
}
}

View file

@ -1,4 +1,4 @@
package org.springframework.samples.petclinic.config;
package org.springframework.samples.petclinic.system;
import java.util.concurrent.TimeUnit;
import javax.cache.CacheManager;
@ -23,7 +23,7 @@ import org.springframework.context.annotation.Profile;
@Configuration
@EnableCaching
@Profile("production")
public class CacheConfig {
class CacheConfig {
@Bean
public JCacheManagerCustomizer cacheManagerCustomizer() {

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.web;
package org.springframework.samples.petclinic.system;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@ -27,7 +27,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
* Also see how a view that resolves to "error" has been added ("error.html").
*/
@Controller
public class CrashController {
class CrashController {
@RequestMapping(value = "/oups", method = RequestMethod.GET)
public String triggerException() {

View file

@ -1,11 +1,11 @@
package org.springframework.samples.petclinic.web;
package org.springframework.samples.petclinic.system;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class WelcomeController {
class WelcomeController {
@RequestMapping("/")
public String welcome() {

View file

@ -13,11 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
package org.springframework.samples.petclinic.vet;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.springframework.samples.petclinic.model.NamedEntity;
/**
* Models a {@link Vet Vet's} specialty (for example, dentistry).
*

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
package org.springframework.samples.petclinic.vet;
import java.util.ArrayList;
import java.util.Collections;
@ -31,6 +31,7 @@ import javax.xml.bind.annotation.XmlElement;
import org.springframework.beans.support.MutableSortDefinition;
import org.springframework.beans.support.PropertyComparator;
import org.springframework.samples.petclinic.model.Person;
/**
* Simple JavaBean domain object representing a veterinarian.

View file

@ -13,13 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.web;
package org.springframework.samples.petclinic.vet;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.samples.petclinic.model.Vets;
import org.springframework.samples.petclinic.service.ClinicService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@ -31,13 +29,13 @@ import org.springframework.web.bind.annotation.ResponseBody;
* @author Arjen Poutsma
*/
@Controller
public class VetController {
class VetController {
private final ClinicService clinicService;
private final VetRepository vets;
@Autowired
public VetController(ClinicService clinicService) {
this.clinicService = clinicService;
public VetController(VetRepository clinicService) {
this.vets = clinicService;
}
@RequestMapping(value = { "/vets.html" })
@ -45,7 +43,7 @@ public class VetController {
// Here we are returning an object of type 'Vets' rather than a collection of Vet
// objects so it is simpler for Object-Xml mapping
Vets vets = new Vets();
vets.getVetList().addAll(this.clinicService.findVets());
vets.getVetList().addAll(this.vets.findAll());
model.put("vets", vets);
return "vets/vetList";
}
@ -55,7 +53,7 @@ public class VetController {
// Here we are returning an object of type 'Vets' rather than a collection of Vet
// objects so it is simpler for JSon/Object mapping
Vets vets = new Vets();
vets.getVetList().addAll(this.clinicService.findVets());
vets.getVetList().addAll(this.vets.findAll());
return vets;
}

View file

@ -13,13 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository;
package org.springframework.samples.petclinic.vet;
import java.util.Collection;
import javax.cache.annotation.CacheResult;
import org.springframework.dao.DataAccessException;
import org.springframework.data.repository.Repository;
import org.springframework.samples.petclinic.model.Vet;
import org.springframework.transaction.annotation.Transactional;
/**
* Repository class for <code>Vet</code> domain objects All method names are compliant with Spring Data naming
@ -37,6 +39,8 @@ public interface VetRepository extends Repository<Vet, Integer> {
*
* @return a <code>Collection</code> of <code>Vet</code>s
*/
@Transactional(readOnly = true)
@CacheResult(cacheName = "vets")
Collection<Vet> findAll() throws DataAccessException;

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
package org.springframework.samples.petclinic.vet;
import java.util.ArrayList;
import java.util.List;

View file

@ -13,24 +13,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.model;
package org.springframework.samples.petclinic.visit;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import java.util.Date;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.samples.petclinic.model.BaseEntity;
/**
* Simple JavaBean domain object representing a visit.
*
* @author Ken Krebs
* @author Dave Syer
*/
@Entity
@Table(name = "visits")
@ -54,9 +55,8 @@ public class Visit extends BaseEntity {
/**
* Holds value of property pet.
*/
@ManyToOne
@JoinColumn(name = "pet_id")
private Pet pet;
@Column(name = "pet_id")
private Integer petId;
/**
@ -104,21 +104,21 @@ public class Visit extends BaseEntity {
}
/**
* Getter for property pet.
* Getter for property pet id.
*
* @return Value of property pet.
* @return Value of property pet id.
*/
public Pet getPet() {
return this.pet;
public Integer getPetId() {
return this.petId;
}
/**
* Setter for property pet.
* Setter for property pet id.
*
* @param pet New value of property pet.
* @param pet New value of property pet id.
*/
public void setPet(Pet pet) {
this.pet = pet;
public void setPetId(Integer petId) {
this.petId = petId;
}
}

View file

@ -13,14 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository;
package org.springframework.samples.petclinic.visit;
import java.util.List;
import org.springframework.dao.DataAccessException;
import org.springframework.data.repository.Repository;
import org.springframework.samples.petclinic.model.BaseEntity;
import org.springframework.samples.petclinic.model.Visit;
/**
* Repository class for <code>Visit</code> domain objects All method names are compliant with Spring Data naming

View file

@ -1,5 +0,0 @@
/**
* The classes in this package represent PetClinic's web presentation layer.
*/
package org.springframework.samples.petclinic.web;