mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-12-27 19:07:28 +00:00
feat: added animal resource
This commit is contained in:
parent
b5a630b199
commit
69f610e69e
3 changed files with 312 additions and 0 deletions
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright 2012-2025 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.model;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.PositiveOrZero;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Simple JavaBean domain object representing an animal.
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public class Animal extends BaseEntity {
|
||||
|
||||
@Column(name = "name")
|
||||
@NotBlank
|
||||
private @Nullable String name;
|
||||
|
||||
@Column(name = "species")
|
||||
@NotBlank
|
||||
private @Nullable String species;
|
||||
|
||||
@Column(name = "breed")
|
||||
@NotBlank
|
||||
private @Nullable String breed;
|
||||
|
||||
@Column(name = "age")
|
||||
@PositiveOrZero
|
||||
private @Nullable Integer age;
|
||||
|
||||
@Column(name = "color")
|
||||
@NotBlank
|
||||
private @Nullable String color;
|
||||
|
||||
@Column(name = "description")
|
||||
private @Nullable String description;
|
||||
|
||||
public @Nullable String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(@Nullable String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public @Nullable String getSpecies() {
|
||||
return this.species;
|
||||
}
|
||||
|
||||
public void setSpecies(@Nullable String species) {
|
||||
this.species = species;
|
||||
}
|
||||
|
||||
public @Nullable String getBreed() {
|
||||
return this.breed;
|
||||
}
|
||||
|
||||
public void setBreed(@Nullable String breed) {
|
||||
this.breed = breed;
|
||||
}
|
||||
|
||||
public @Nullable Integer getAge() {
|
||||
return this.age;
|
||||
}
|
||||
|
||||
public void setAge(@Nullable Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public @Nullable String getColor() {
|
||||
return this.color;
|
||||
}
|
||||
|
||||
public void setColor(@Nullable String color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public @Nullable String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
public void setDescription(@Nullable String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright 2012-2025 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.animal;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.samples.petclinic.model.Animal;
|
||||
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.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;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
/**
|
||||
* Controller class for managing {@link Animal} entities.
|
||||
*
|
||||
* Mirrors the structure of the PetController from Spring PetClinic.
|
||||
*
|
||||
* Author list follows PetClinic conventions.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Ken Krebs
|
||||
* @author Arjen Poutsma
|
||||
* @author Wick Dynex
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/animals")
|
||||
class AnimalController {
|
||||
|
||||
private static final String VIEWS_ANIMALS_CREATE_OR_UPDATE_FORM = "animals/createOrUpdateAnimalForm";
|
||||
|
||||
private final AnimalRepository animals;
|
||||
|
||||
public AnimalController(AnimalRepository animals) {
|
||||
this.animals = animals;
|
||||
}
|
||||
|
||||
@ModelAttribute("animal")
|
||||
public @Nullable Animal findAnimal(@PathVariable(name = "animalId", required = false) @Nullable Integer id) {
|
||||
if (id == null) {
|
||||
return new Animal();
|
||||
}
|
||||
|
||||
Optional<Animal> optional = this.animals.findById(id);
|
||||
return optional.orElseThrow(() -> new IllegalArgumentException(
|
||||
"Animal not found with id: " + id + ". Please ensure the ID is correct"));
|
||||
}
|
||||
|
||||
@InitBinder("animal")
|
||||
public void initAnimalBinder(WebDataBinder dataBinder) {
|
||||
dataBinder.setDisallowedFields("id");
|
||||
}
|
||||
|
||||
@GetMapping("/new")
|
||||
public String initCreationForm(ModelMap model) {
|
||||
model.put("animal", new Animal());
|
||||
return VIEWS_ANIMALS_CREATE_OR_UPDATE_FORM;
|
||||
}
|
||||
|
||||
@PostMapping("/new")
|
||||
public String processCreationForm(@Valid Animal animal, BindingResult result,
|
||||
RedirectAttributes redirectAttributes) {
|
||||
|
||||
// Example validation similar to name duplicate logic in PetController
|
||||
if (StringUtils.hasText(animal.getName())) {
|
||||
boolean exists = this.animals.findAll().stream()
|
||||
.anyMatch(a -> animal.getName().equalsIgnoreCase(a.getName()));
|
||||
|
||||
if (exists) {
|
||||
result.rejectValue("name", "duplicate", "already exists");
|
||||
}
|
||||
}
|
||||
|
||||
if (result.hasErrors()) {
|
||||
return VIEWS_ANIMALS_CREATE_OR_UPDATE_FORM;
|
||||
}
|
||||
|
||||
this.animals.save(animal);
|
||||
redirectAttributes.addFlashAttribute("message", "New Animal has been added");
|
||||
return "redirect:/animals";
|
||||
}
|
||||
|
||||
@GetMapping("/{animalId}/edit")
|
||||
public String initUpdateForm() {
|
||||
return VIEWS_ANIMALS_CREATE_OR_UPDATE_FORM;
|
||||
}
|
||||
|
||||
@PostMapping("/{animalId}/edit")
|
||||
public String processUpdateForm(@Valid Animal animal, BindingResult result,
|
||||
RedirectAttributes redirectAttributes) {
|
||||
|
||||
String name = animal.getName();
|
||||
|
||||
if (StringUtils.hasText(name)) {
|
||||
boolean exists = this.animals.findAll().stream()
|
||||
.anyMatch(a -> a.getName().equalsIgnoreCase(name)
|
||||
&& !a.getId().equals(animal.getId()));
|
||||
|
||||
if (exists) {
|
||||
result.rejectValue("name", "duplicate", "already exists");
|
||||
}
|
||||
}
|
||||
|
||||
if (result.hasErrors()) {
|
||||
return VIEWS_ANIMALS_CREATE_OR_UPDATE_FORM;
|
||||
}
|
||||
|
||||
this.animals.save(animal);
|
||||
redirectAttributes.addFlashAttribute("message", "Animal details have been updated");
|
||||
return "redirect:/animals";
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public String listAnimals(ModelMap model) {
|
||||
model.put("animals", this.animals.findAll());
|
||||
return "animals/animalList";
|
||||
}
|
||||
|
||||
@GetMapping("/{animalId}")
|
||||
public String showAnimal(@PathVariable("animalId") int animalId, ModelMap model) {
|
||||
Animal animal = this.animals.findById(animalId).orElseThrow(
|
||||
() -> new IllegalArgumentException("Animal not found with id " + animalId));
|
||||
model.put("animal", animal);
|
||||
return "animals/animalDetails";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright 2012-2025 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.animal;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import jakarta.annotation.Nonnull;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.samples.petclinic.model.Animal;
|
||||
|
||||
/**
|
||||
* Repository class for {@link Animal} domain objects. All method names follow
|
||||
* Spring Data JPA naming conventions. See:
|
||||
* https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-creation
|
||||
*
|
||||
* Provides operations for querying Animals by their attributes.
|
||||
*
|
||||
* Author list follows PetClinic conventions.
|
||||
*
|
||||
* @author Ken Krebs
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @author Michael Isvy
|
||||
* @author Wick Dynex
|
||||
*/
|
||||
public interface AnimalRepository extends JpaRepository<Animal, Integer> {
|
||||
|
||||
/**
|
||||
* Retrieve {@link Animal}s from the data store by species, returning all animals
|
||||
* whose species <i>starts</i> with the given value.
|
||||
* @param species value to search for
|
||||
* @return a Page of matching {@link Animal}s (or an empty page if none found)
|
||||
*/
|
||||
Page<Animal> findBySpeciesStartingWith(String species, Pageable pageable);
|
||||
|
||||
/**
|
||||
* Retrieve an {@link Animal} from the data store by id.
|
||||
* <p>
|
||||
* This method returns an {@link Optional} containing the {@link Animal} if found.
|
||||
* If no animal is found with the provided id, it returns an empty {@link Optional}.
|
||||
* </p>
|
||||
* @param id the id to search for
|
||||
* @return an {@link Optional} containing the {@link Animal} if found, or empty otherwise
|
||||
* @throws IllegalArgumentException if the id is null
|
||||
*/
|
||||
Optional<Animal> findById(Integer id);
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue