mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-07-15 20:25:50 +00:00
fixed lazy loading issues
also renamed some local variables in Unit tests
This commit is contained in:
parent
56c7671939
commit
f44e383462
7 changed files with 52 additions and 54 deletions
|
@ -9,6 +9,7 @@ import java.util.Set;
|
||||||
import javax.persistence.CascadeType;
|
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.OneToMany;
|
||||||
|
@ -41,7 +42,7 @@ public class Pet extends NamedEntity {
|
||||||
@JoinColumn(name = "owner_id")
|
@JoinColumn(name = "owner_id")
|
||||||
private Owner owner;
|
private Owner owner;
|
||||||
|
|
||||||
@OneToMany(cascade=CascadeType.ALL, mappedBy="pet")
|
@OneToMany(cascade=CascadeType.ALL, mappedBy="pet", fetch=FetchType.EAGER)
|
||||||
private Set<Visit> visits;
|
private Set<Visit> visits;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -120,16 +120,16 @@ public class JdbcOwnerRepositoryImpl implements OwnerRepository {
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void save(Owner owner) throws DataAccessException {
|
public void save(Owner owner) throws DataAccessException {
|
||||||
|
BeanPropertySqlParameterSource parameterSource = new BeanPropertySqlParameterSource(owner);
|
||||||
if (owner.isNew()) {
|
if (owner.isNew()) {
|
||||||
Number newKey = this.insertOwner.executeAndReturnKey(
|
Number newKey = this.insertOwner.executeAndReturnKey(parameterSource);
|
||||||
new BeanPropertySqlParameterSource(owner));
|
|
||||||
owner.setId(newKey.intValue());
|
owner.setId(newKey.intValue());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.namedParameterJdbcTemplate.update(
|
this.namedParameterJdbcTemplate.update(
|
||||||
"UPDATE owners SET first_name=:firstName, last_name=:lastName, address=:address, " +
|
"UPDATE owners SET first_name=:firstName, last_name=:lastName, address=:address, " +
|
||||||
"city=:city, telephone=:telephone WHERE id=:id",
|
"city=:city, telephone=:telephone WHERE id=:id",
|
||||||
new BeanPropertySqlParameterSource(owner));
|
parameterSource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import javax.persistence.EntityManager;
|
||||||
import javax.persistence.PersistenceContext;
|
import javax.persistence.PersistenceContext;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
|
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
import org.springframework.samples.petclinic.Owner;
|
import org.springframework.samples.petclinic.Owner;
|
||||||
import org.springframework.samples.petclinic.repository.OwnerRepository;
|
import org.springframework.samples.petclinic.repository.OwnerRepository;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
@ -32,13 +33,19 @@ public class JpaOwnerRepositoryImpl implements OwnerRepository {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Collection<Owner> findByLastName(String lastName) {
|
public Collection<Owner> findByLastName(String lastName) {
|
||||||
Query query = this.em.createQuery("SELECT owner FROM Owner owner WHERE owner.lastName LIKE :lastName");
|
// using 'join fetch' because a single query should load both owners and pets
|
||||||
|
// using 'left join fetch' because it might happen that an owner does not have pets yet
|
||||||
|
Query query = this.em.createQuery("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.lastName LIKE :lastName");
|
||||||
query.setParameter("lastName", lastName + "%");
|
query.setParameter("lastName", lastName + "%");
|
||||||
return query.getResultList();
|
return query.getResultList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Owner findById(int id) {
|
public Owner findById(int id) {
|
||||||
return this.em.find(Owner.class, id);
|
// using 'join fetch' because a single query should load both owners and pets
|
||||||
|
// using 'left join fetch' because it might happen that an owner does not have pets yet
|
||||||
|
Query query = this.em.createQuery("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:id");
|
||||||
|
query.setParameter("id", id);
|
||||||
|
return (Owner) query.getSingleResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ public class JpaVetRepositoryImpl implements VetRepository {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Collection<Vet> findAll() {
|
public Collection<Vet> findAll() {
|
||||||
return this.em.createQuery("SELECT vet FROM Vet vet ORDER BY vet.lastName, vet.firstName").getResultList();
|
return this.em.createQuery("SELECT vet FROM Vet vet join fetch vet.specialties ORDER BY vet.lastName, vet.firstName").getResultList();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,22 +97,13 @@ public abstract class AbstractOwnerRepositoryTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test @Transactional
|
@Test @Transactional
|
||||||
public void findOwner() {
|
public void findSingleOwner() {
|
||||||
Owner o1 = this.ownerRepository.findById(1);
|
Owner owner1 = this.ownerRepository.findById(1);
|
||||||
assertTrue(o1.getLastName().startsWith("Franklin"));
|
assertTrue(owner1.getLastName().startsWith("Franklin"));
|
||||||
Owner o10 = this.ownerRepository.findById(10);
|
Owner owner10 = this.ownerRepository.findById(10);
|
||||||
assertEquals("Carlos", o10.getFirstName());
|
assertEquals("Carlos", owner10.getFirstName());
|
||||||
|
|
||||||
// XXX: Add programmatic support for ending transactions with the
|
assertEquals(owner1.getPets().size(), 1);
|
||||||
// TestContext Framework.
|
|
||||||
|
|
||||||
// Check lazy loading, by ending the transaction:
|
|
||||||
// endTransaction();
|
|
||||||
|
|
||||||
// Now Owners are "disconnected" from the data store.
|
|
||||||
// We might need to touch this collection if we switched to lazy loading
|
|
||||||
// in mapping files, but this test would pick this up.
|
|
||||||
o1.getPets();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test @Transactional
|
@Test @Transactional
|
||||||
|
|
|
@ -97,51 +97,51 @@ public abstract class AbstractPetRepositoryTests {
|
||||||
public void getPetTypes() {
|
public void getPetTypes() {
|
||||||
Collection<PetType> petTypes = this.petRepository.findPetTypes();
|
Collection<PetType> petTypes = this.petRepository.findPetTypes();
|
||||||
|
|
||||||
PetType t1 = EntityUtils.getById(petTypes, PetType.class, 1);
|
PetType petType1 = EntityUtils.getById(petTypes, PetType.class, 1);
|
||||||
assertEquals("cat", t1.getName());
|
assertEquals("cat", petType1.getName());
|
||||||
PetType t4 = EntityUtils.getById(petTypes, PetType.class, 4);
|
PetType petType4 = EntityUtils.getById(petTypes, PetType.class, 4);
|
||||||
assertEquals("snake", t4.getName());
|
assertEquals("snake", petType4.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void findPet() {
|
public void findPet() {
|
||||||
Collection<PetType> types = this.petRepository.findPetTypes();
|
Collection<PetType> types = this.petRepository.findPetTypes();
|
||||||
Pet p7 = this.petRepository.findById(7);
|
Pet pet7 = this.petRepository.findById(7);
|
||||||
assertTrue(p7.getName().startsWith("Samantha"));
|
assertTrue(pet7.getName().startsWith("Samantha"));
|
||||||
assertEquals(EntityUtils.getById(types, PetType.class, 1).getId(), p7.getType().getId());
|
assertEquals(EntityUtils.getById(types, PetType.class, 1).getId(), pet7.getType().getId());
|
||||||
assertEquals("Jean", p7.getOwner().getFirstName());
|
assertEquals("Jean", pet7.getOwner().getFirstName());
|
||||||
Pet p6 = this.petRepository.findById(6);
|
Pet pet6 = this.petRepository.findById(6);
|
||||||
assertEquals("George", p6.getName());
|
assertEquals("George", pet6.getName());
|
||||||
assertEquals(EntityUtils.getById(types, PetType.class, 4).getId(), p6.getType().getId());
|
assertEquals(EntityUtils.getById(types, PetType.class, 4).getId(), pet6.getType().getId());
|
||||||
assertEquals("Peter", p6.getOwner().getFirstName());
|
assertEquals("Peter", pet6.getOwner().getFirstName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test @Transactional
|
@Test @Transactional
|
||||||
public void insertPet() {
|
public void insertPet() {
|
||||||
Owner o6 = this.ownerRepository.findById(6);
|
Owner owner6 = this.ownerRepository.findById(6);
|
||||||
int found = o6.getPets().size();
|
int found = owner6.getPets().size();
|
||||||
Pet pet = new Pet();
|
Pet pet = new Pet();
|
||||||
pet.setName("bowser");
|
pet.setName("bowser");
|
||||||
Collection<PetType> types = this.petRepository.findPetTypes();
|
Collection<PetType> types = this.petRepository.findPetTypes();
|
||||||
pet.setType(EntityUtils.getById(types, PetType.class, 2));
|
pet.setType(EntityUtils.getById(types, PetType.class, 2));
|
||||||
pet.setBirthDate(new DateTime());
|
pet.setBirthDate(new DateTime());
|
||||||
o6.addPet(pet);
|
owner6.addPet(pet);
|
||||||
assertEquals(found + 1, o6.getPets().size());
|
assertEquals(found + 1, owner6.getPets().size());
|
||||||
// both storePet and storeOwner are necessary to cover all ORM tools
|
// both storePet and storeOwner are necessary to cover all ORM tools
|
||||||
this.petRepository.save(pet);
|
this.petRepository.save(pet);
|
||||||
this.ownerRepository.save(o6);
|
this.ownerRepository.save(owner6);
|
||||||
o6 = this.ownerRepository.findById(6);
|
owner6 = this.ownerRepository.findById(6);
|
||||||
assertEquals(found + 1, o6.getPets().size());
|
assertEquals(found + 1, owner6.getPets().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test @Transactional
|
@Test @Transactional
|
||||||
public void updatePet() throws Exception {
|
public void updatePet() throws Exception {
|
||||||
Pet p7 = this.petRepository.findById(7);
|
Pet pet7 = this.petRepository.findById(7);
|
||||||
String old = p7.getName();
|
String old = pet7.getName();
|
||||||
p7.setName(old + "X");
|
pet7.setName(old + "X");
|
||||||
this.petRepository.save(p7);
|
this.petRepository.save(pet7);
|
||||||
p7 = this.petRepository.findById(7);
|
pet7 = this.petRepository.findById(7);
|
||||||
assertEquals(old + "X", p7.getName());
|
assertEquals(old + "X", pet7.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,17 +90,16 @@ public abstract class AbstractVisitRepositoryTests {
|
||||||
|
|
||||||
@Test @Transactional
|
@Test @Transactional
|
||||||
public void insertVisit() {
|
public void insertVisit() {
|
||||||
Pet p7 = this.petRepository.findById(7);
|
Pet pet7 = this.petRepository.findById(7);
|
||||||
int found = p7.getVisits().size();
|
int found = pet7.getVisits().size();
|
||||||
Visit visit = new Visit();
|
Visit visit = new Visit();
|
||||||
p7.addVisit(visit);
|
pet7.addVisit(visit);
|
||||||
visit.setDescription("test");
|
visit.setDescription("test");
|
||||||
// both storeVisit and storePet are necessary to cover all ORM tools
|
// both storeVisit and storePet are necessary to cover all ORM tools
|
||||||
this.visitRepository.save(visit);
|
this.visitRepository.save(visit);
|
||||||
this.petRepository.save(p7);
|
this.petRepository.save(pet7);
|
||||||
// assertTrue(!visit.isNew()); -- NOT TRUE FOR TOPLINK (before commit)
|
pet7 = this.petRepository.findById(7);
|
||||||
p7 = this.petRepository.findById(7);
|
assertEquals(found + 1, pet7.getVisits().size());
|
||||||
assertEquals(found + 1, p7.getVisits().size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue