Skip to content
Snippets Groups Projects
Commit f44e3834 authored by Mic's avatar Mic
Browse files

fixed lazy loading issues

also renamed some local variables in Unit tests
parent 56c76719
No related branches found
No related tags found
No related merge requests found
...@@ -9,6 +9,7 @@ import java.util.Set; ...@@ -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 { ...@@ -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 { ...@@ -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; ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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
// TestContext Framework.
// Check lazy loading, by ending the transaction:
// endTransaction();
// Now Owners are "disconnected" from the data store. assertEquals(owner1.getPets().size(), 1);
// 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 { ...@@ -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 { ...@@ -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());
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment