mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-04-25 03:42:48 +00:00
Remove manual id management in child entities
This is reverting a workaround for a Hibernate "feature". There's no need for the child entities (Pet and Visit) to know about their parent (foreign key). Hibernate can manage that just fine with a @JoinColumn. But it needs a nullable foreign key column in the DB schema. That's the downside. The upside is much less code in Java.
This commit is contained in:
parent
43beff91a3
commit
b559077f14
10 changed files with 25 additions and 60 deletions
|
@ -16,22 +16,19 @@
|
|||
package org.springframework.samples.petclinic.owner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
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.OneToMany;
|
||||
import javax.persistence.OrderBy;
|
||||
import javax.persistence.Table;
|
||||
import javax.validation.constraints.Digits;
|
||||
import javax.validation.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;
|
||||
|
||||
|
@ -60,8 +57,10 @@ public class Owner extends Person {
|
|||
@Digits(fraction = 0, integer = 10)
|
||||
private String telephone;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "ownerId", fetch = FetchType.EAGER)
|
||||
private Set<Pet> pets;
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "owner_id")
|
||||
@OrderBy("name")
|
||||
private List<Pet> pets = new ArrayList<>();
|
||||
|
||||
public String getAddress() {
|
||||
return this.address;
|
||||
|
@ -87,28 +86,14 @@ public class Owner extends Person {
|
|||
this.telephone = telephone;
|
||||
}
|
||||
|
||||
protected Set<Pet> getPetsInternal() {
|
||||
if (this.pets == null) {
|
||||
this.pets = new HashSet<>();
|
||||
}
|
||||
return this.pets;
|
||||
}
|
||||
|
||||
protected void setPetsInternal(Set<Pet> pets) {
|
||||
this.pets = pets;
|
||||
}
|
||||
|
||||
public List<Pet> getPets() {
|
||||
List<Pet> sortedPets = new ArrayList<>(getPetsInternal());
|
||||
PropertyComparator.sort(sortedPets, new MutableSortDefinition("name", true, true));
|
||||
return Collections.unmodifiableList(sortedPets);
|
||||
return this.pets;
|
||||
}
|
||||
|
||||
public void addPet(Pet pet) {
|
||||
if (pet.isNew()) {
|
||||
getPetsInternal().add(pet);
|
||||
getPets().add(pet);
|
||||
}
|
||||
pet.setOwnerId(getId());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,7 +111,7 @@ public class Owner extends Person {
|
|||
* @return a pet if pet id is already in use
|
||||
*/
|
||||
public Pet getPet(Integer id) {
|
||||
for (Pet pet : getPetsInternal()) {
|
||||
for (Pet pet : getPets()) {
|
||||
if (!pet.isNew()) {
|
||||
Integer compId = pet.getId();
|
||||
if (compId.equals(id)) {
|
||||
|
@ -144,7 +129,7 @@ public class Owner extends Person {
|
|||
*/
|
||||
public Pet getPet(String name, boolean ignoreNew) {
|
||||
name = name.toLowerCase();
|
||||
for (Pet pet : getPetsInternal()) {
|
||||
for (Pet pet : getPets()) {
|
||||
if (!ignoreNew || !pet.isNew()) {
|
||||
String compName = pet.getName();
|
||||
compName = compName == null ? "" : compName.toLowerCase();
|
||||
|
|
|
@ -52,17 +52,11 @@ public class Pet extends NamedEntity {
|
|||
@JoinColumn(name = "type_id")
|
||||
private PetType type;
|
||||
|
||||
@Column
|
||||
private Integer ownerId;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "petId", fetch = FetchType.LAZY)
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "pet_id")
|
||||
@OrderBy("visit_date ASC")
|
||||
private Set<Visit> visits = new LinkedHashSet<>();
|
||||
|
||||
public void setOwnerId(Integer ownerId) {
|
||||
this.ownerId = ownerId;
|
||||
}
|
||||
|
||||
public void setBirthDate(LocalDate birthDate) {
|
||||
this.birthDate = birthDate;
|
||||
}
|
||||
|
@ -85,7 +79,6 @@ public class Pet extends NamedEntity {
|
|||
|
||||
public void addVisit(Visit visit) {
|
||||
getVisits().add(visit);
|
||||
visit.setPetId(this.getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -40,12 +40,8 @@ public class Visit extends BaseEntity {
|
|||
private LocalDate date;
|
||||
|
||||
@NotEmpty
|
||||
@Column
|
||||
private String description;
|
||||
|
||||
@Column
|
||||
private Integer petId;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Visit for the current date
|
||||
*/
|
||||
|
@ -69,12 +65,4 @@ public class Visit extends BaseEntity {
|
|||
this.description = description;
|
||||
}
|
||||
|
||||
public Integer getPetId() {
|
||||
return this.petId;
|
||||
}
|
||||
|
||||
public void setPetId(Integer petId) {
|
||||
this.petId = petId;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -78,12 +78,13 @@ class VisitController {
|
|||
// Spring MVC calls method loadPetWithVisit(...) before processNewVisitForm is
|
||||
// called
|
||||
@PostMapping("/owners/{ownerId}/pets/{petId}/visits/new")
|
||||
public String processNewVisitForm(@ModelAttribute Owner owner, @Valid Visit visit, BindingResult result) {
|
||||
public String processNewVisitForm(@ModelAttribute Owner owner, @PathVariable("petId") int petId, @Valid Visit visit,
|
||||
BindingResult result) {
|
||||
if (result.hasErrors()) {
|
||||
return "pets/createOrUpdateVisitForm";
|
||||
}
|
||||
else {
|
||||
owner.getPet(visit.getPetId()).addVisit(visit);
|
||||
owner.getPet(petId).addVisit(visit);
|
||||
this.owners.save(owner);
|
||||
return "redirect:/owners/{ownerId}";
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ CREATE TABLE pets (
|
|||
name VARCHAR(30),
|
||||
birth_date DATE,
|
||||
type_id INTEGER NOT NULL,
|
||||
owner_id INTEGER NOT NULL
|
||||
owner_id INTEGER
|
||||
);
|
||||
ALTER TABLE pets ADD CONSTRAINT fk_pets_owners FOREIGN KEY (owner_id) REFERENCES owners (id);
|
||||
ALTER TABLE pets ADD CONSTRAINT fk_pets_types FOREIGN KEY (type_id) REFERENCES types (id);
|
||||
|
@ -56,7 +56,7 @@ CREATE INDEX pets_name ON pets (name);
|
|||
|
||||
CREATE TABLE visits (
|
||||
id INTEGER IDENTITY PRIMARY KEY,
|
||||
pet_id INTEGER NOT NULL,
|
||||
pet_id INTEGER,
|
||||
visit_date DATE,
|
||||
description VARCHAR(255)
|
||||
);
|
||||
|
|
|
@ -48,7 +48,7 @@ CREATE TABLE pets (
|
|||
name VARCHAR(30),
|
||||
birth_date DATE,
|
||||
type_id INTEGER NOT NULL,
|
||||
owner_id INTEGER NOT NULL
|
||||
owner_id INTEGER
|
||||
);
|
||||
ALTER TABLE pets ADD CONSTRAINT fk_pets_owners FOREIGN KEY (owner_id) REFERENCES owners (id);
|
||||
ALTER TABLE pets ADD CONSTRAINT fk_pets_types FOREIGN KEY (type_id) REFERENCES types (id);
|
||||
|
@ -56,7 +56,7 @@ CREATE INDEX pets_name ON pets (name);
|
|||
|
||||
CREATE TABLE visits (
|
||||
id INTEGER IDENTITY PRIMARY KEY,
|
||||
pet_id INTEGER NOT NULL,
|
||||
pet_id INTEGER,
|
||||
visit_date DATE,
|
||||
description VARCHAR(255)
|
||||
);
|
||||
|
|
|
@ -40,7 +40,7 @@ CREATE TABLE IF NOT EXISTS pets (
|
|||
name VARCHAR(30),
|
||||
birth_date DATE,
|
||||
type_id INT(4) UNSIGNED NOT NULL,
|
||||
owner_id INT(4) UNSIGNED NOT NULL,
|
||||
owner_id INT(4) UNSIGNED,
|
||||
INDEX(name),
|
||||
FOREIGN KEY (owner_id) REFERENCES owners(id),
|
||||
FOREIGN KEY (type_id) REFERENCES types(id)
|
||||
|
@ -48,7 +48,7 @@ CREATE TABLE IF NOT EXISTS pets (
|
|||
|
||||
CREATE TABLE IF NOT EXISTS visits (
|
||||
id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
pet_id INT(4) UNSIGNED NOT NULL,
|
||||
pet_id INT(4) UNSIGNED,
|
||||
visit_date DATE,
|
||||
description VARCHAR(255),
|
||||
FOREIGN KEY (pet_id) REFERENCES pets(id)
|
||||
|
|
|
@ -38,14 +38,14 @@ CREATE TABLE IF NOT EXISTS pets (
|
|||
name TEXT,
|
||||
birth_date DATE,
|
||||
type_id INT NOT NULL REFERENCES types (id),
|
||||
owner_id INT NOT NULL REFERENCES owners (id)
|
||||
owner_id INT REFERENCES owners (id)
|
||||
);
|
||||
CREATE INDEX ON pets (name);
|
||||
CREATE INDEX ON pets (owner_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS visits (
|
||||
id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
pet_id INT NOT NULL REFERENCES pets (id),
|
||||
pet_id INT REFERENCES pets (id),
|
||||
visit_date DATE,
|
||||
description TEXT
|
||||
);
|
||||
|
|
|
@ -75,11 +75,11 @@ class OwnerControllerTests {
|
|||
Pet max = new Pet();
|
||||
PetType dog = new PetType();
|
||||
dog.setName("dog");
|
||||
max.setId(1);
|
||||
max.setType(dog);
|
||||
max.setName("Max");
|
||||
max.setBirthDate(LocalDate.now());
|
||||
george.setPetsInternal(Collections.singleton(max));
|
||||
george.addPet(max);
|
||||
max.setId(1);
|
||||
return george;
|
||||
};
|
||||
|
||||
|
@ -95,7 +95,6 @@ class OwnerControllerTests {
|
|||
given(this.owners.findById(TEST_OWNER_ID)).willReturn(george);
|
||||
Visit visit = new Visit();
|
||||
visit.setDate(LocalDate.now());
|
||||
visit.setPetId(george.getPet("Max").getId());
|
||||
george.getPet("Max").getVisits().add(visit);
|
||||
|
||||
}
|
||||
|
|
|
@ -216,7 +216,6 @@ class ClinicServiceTests {
|
|||
assertThat(visits).hasSize(2);
|
||||
Visit[] visitArr = visits.toArray(new Visit[visits.size()]);
|
||||
assertThat(visitArr[0].getDate()).isNotNull();
|
||||
assertThat(visitArr[0].getPetId()).isEqualTo(7);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue