From c9c8c4e085015b14ca6c3db077bac05e36859907 Mon Sep 17 00:00:00 2001
From: Mic <misvy@vmware.com>
Date: Thu, 17 Jan 2013 15:27:27 +0800
Subject: [PATCH] moved the ClinicRepository into some separate repos

There is still some polish up to be done.
---
 .../samples/petclinic/Clinic.java             |  82 -----
 .../samples/petclinic/Owner.java              |   7 -
 .../petclinic/aspects/UsageLogAspect.java     |   2 +-
 .../petclinic/jdbc/JdbcClinicImpl.java        | 344 ------------------
 .../petclinic/repository/OwnerRepository.java |  47 +++
 .../petclinic/repository/PetRepository.java   |  51 +++
 .../petclinic/repository/VetRepository.java   |  27 ++
 .../petclinic/repository/VisitRepository.java |  30 ++
 .../jdbc/JdbcClinicImplMBean.java             |   6 +-
 .../jdbc/JdbcOwnerRepositoryImpl.java         | 173 +++++++++
 .../{ => repository}/jdbc/JdbcPet.java        |   4 +-
 .../jdbc/JdbcPetRepositoryImpl.java           | 160 ++++++++
 .../repository/jdbc/JdbcPetRowMapper.java     |  23 ++
 .../jdbc/JdbcVetRepositoryImpl.java           | 118 ++++++
 .../jdbc/JdbcVisitRepositoryImpl.java         | 131 +++++++
 .../{ => repository}/jdbc/package-info.java   |   2 +-
 .../{ => repository}/jpa/JpaClinicImpl.java   |   8 +-
 .../jpa/JpaOwnerRepositoryImpl.java           |  57 +++
 .../jpa/SpringDataClinic.java                 |   6 +-
 .../jpa/SpringDataOwnerRepository.java        |  13 +
 .../{ => repository}/jpa/package-info.java    |   2 +-
 .../petclinic/service/ClinicService.java      |  39 ++
 .../petclinic/service/ClinicServiceImpl.java  |  71 ++++
 .../web/ClinicBindingInitializer.java         |   6 +-
 .../petclinic/web/ClinicController.java       |  99 -----
 .../petclinic/web/OwnerController.java        |  30 +-
 .../samples/petclinic/web/PetController.java  |  24 +-
 .../samples/petclinic/web/PetTypeEditor.java  |  10 +-
 .../samples/petclinic/web/VetController.java  |  54 +++
 .../petclinic/web/VisitController.java        |  30 +-
 .../samples/petclinic/web/VisitsAtomView.java |   2 +-
 .../spring/applicationContext-dao.xml         |  18 +-
 src/main/webapp/WEB-INF/petclinic-servlet.xml |   4 +-
 .../AbstractOwnerRepositoryTests.java         | 147 ++++++++
 ...s.java => AbstractPetRepositoryTests.java} | 122 ++-----
 .../petclinic/AbstractVetRepositoryTests.java | 107 ++++++
 .../AbstractVisitRepositoryTests.java         | 111 ++++++
 .../aspects/UsageLogAspectTests.java          |  15 +-
 .../jdbc/JdbcOwnerRepositoryImplTests.java    |  29 ++
 ...s.java => JdbcPetRepositoryImplTests.java} |   5 +-
 .../jdbc/JdbcVetRepositoryImplTests.java      |  29 ++
 .../jdbc/JdbcVisitRepositoryImplTests.java    |  29 ++
 ....java => JpaOwnerRepositoryImplTests.java} |  29 +-
 .../jpa/JpaPetRepositoryImplTests.java        |  29 ++
 .../jpa/JpaVetRepositoryImplTests.java        |  29 ++
 .../jpa/JpaVisitRepositoryImplTests.java      |  29 ++
 ...va => SpringDataOwnerRepositoryTests.java} |   4 +-
 47 files changed, 1666 insertions(+), 728 deletions(-)
 delete mode 100644 src/main/java/org/springframework/samples/petclinic/Clinic.java
 delete mode 100644 src/main/java/org/springframework/samples/petclinic/jdbc/JdbcClinicImpl.java
 create mode 100644 src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java
 create mode 100644 src/main/java/org/springframework/samples/petclinic/repository/PetRepository.java
 create mode 100644 src/main/java/org/springframework/samples/petclinic/repository/VetRepository.java
 create mode 100644 src/main/java/org/springframework/samples/petclinic/repository/VisitRepository.java
 rename src/main/java/org/springframework/samples/petclinic/{ => repository}/jdbc/JdbcClinicImplMBean.java (59%)
 create mode 100644 src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcOwnerRepositoryImpl.java
 rename src/main/java/org/springframework/samples/petclinic/{ => repository}/jdbc/JdbcPet.java (78%)
 create mode 100644 src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcPetRepositoryImpl.java
 create mode 100644 src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcPetRowMapper.java
 create mode 100644 src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVetRepositoryImpl.java
 create mode 100644 src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVisitRepositoryImpl.java
 rename src/main/java/org/springframework/samples/petclinic/{ => repository}/jdbc/package-info.java (62%)
 rename src/main/java/org/springframework/samples/petclinic/{ => repository}/jpa/JpaClinicImpl.java (89%)
 create mode 100644 src/main/java/org/springframework/samples/petclinic/repository/jpa/JpaOwnerRepositoryImpl.java
 rename src/main/java/org/springframework/samples/petclinic/{ => repository}/jpa/SpringDataClinic.java (83%)
 create mode 100644 src/main/java/org/springframework/samples/petclinic/repository/jpa/SpringDataOwnerRepository.java
 rename src/main/java/org/springframework/samples/petclinic/{ => repository}/jpa/package-info.java (62%)
 create mode 100644 src/main/java/org/springframework/samples/petclinic/service/ClinicService.java
 create mode 100644 src/main/java/org/springframework/samples/petclinic/service/ClinicServiceImpl.java
 delete mode 100644 src/main/java/org/springframework/samples/petclinic/web/ClinicController.java
 create mode 100644 src/main/java/org/springframework/samples/petclinic/web/VetController.java
 create mode 100644 src/test/java/org/springframework/samples/petclinic/AbstractOwnerRepositoryTests.java
 rename src/test/java/org/springframework/samples/petclinic/{AbstractClinicTests.java => AbstractPetRepositoryTests.java} (60%)
 create mode 100644 src/test/java/org/springframework/samples/petclinic/AbstractVetRepositoryTests.java
 create mode 100644 src/test/java/org/springframework/samples/petclinic/AbstractVisitRepositoryTests.java
 create mode 100644 src/test/java/org/springframework/samples/petclinic/jdbc/JdbcOwnerRepositoryImplTests.java
 rename src/test/java/org/springframework/samples/petclinic/jdbc/{JdbcClinicImplTests.java => JdbcPetRepositoryImplTests.java} (74%)
 create mode 100644 src/test/java/org/springframework/samples/petclinic/jdbc/JdbcVetRepositoryImplTests.java
 create mode 100644 src/test/java/org/springframework/samples/petclinic/jdbc/JdbcVisitRepositoryImplTests.java
 rename src/test/java/org/springframework/samples/petclinic/jpa/{JpaClinicImplTests.java => JpaOwnerRepositoryImplTests.java} (57%)
 create mode 100644 src/test/java/org/springframework/samples/petclinic/jpa/JpaPetRepositoryImplTests.java
 create mode 100644 src/test/java/org/springframework/samples/petclinic/jpa/JpaVetRepositoryImplTests.java
 create mode 100644 src/test/java/org/springframework/samples/petclinic/jpa/JpaVisitRepositoryImplTests.java
 rename src/test/java/org/springframework/samples/petclinic/jpa/{SpringDataClinicTests.java => SpringDataOwnerRepositoryTests.java} (75%)

diff --git a/src/main/java/org/springframework/samples/petclinic/Clinic.java b/src/main/java/org/springframework/samples/petclinic/Clinic.java
deleted file mode 100644
index 9eca087..0000000
--- a/src/main/java/org/springframework/samples/petclinic/Clinic.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.springframework.samples.petclinic;
-
-import java.util.Collection;
-
-import org.springframework.dao.DataAccessException;
-
-/**
- * The high-level PetClinic business interface.
- *
- * <p>This is basically a data access object.
- * PetClinic doesn't have a dedicated business facade.
- *
- * @author Ken Krebs
- * @author Juergen Hoeller
- * @author Sam Brannen
- */
-public interface Clinic {
-
-	/**
-	 * Retrieve all <code>Vet</code>s from the data store.
-	 * @return a <code>Collection</code> of <code>Vet</code>s
-	 */
-	Collection<Vet> getVets() throws DataAccessException;
-
-	/**
-	 * Retrieve all <code>PetType</code>s from the data store.
-	 * @return a <code>Collection</code> of <code>PetType</code>s
-	 */
-	Collection<PetType> getPetTypes() throws DataAccessException;
-
-	/**
-	 * Retrieve <code>Owner</code>s from the data store by last name,
-	 * returning all owners whose last name <i>starts</i> with the given name.
-	 * @param lastName Value to search for
-	 * @return a <code>Collection</code> of matching <code>Owner</code>s
-	 * (or an empty <code>Collection</code> if none found)
-	 */
-	Collection<Owner> findOwners(String lastName) throws DataAccessException;
-
-	/**
-	 * Retrieve an <code>Owner</code> from the data store by id.
-	 * @param id the id to search for
-	 * @return the <code>Owner</code> if found
-	 * @throws org.springframework.dao.DataRetrievalFailureException if not found
-	 */
-	Owner findOwner(int id) throws DataAccessException;
-
-	/**
-	 * Retrieve a <code>Pet</code> from the data store by id.
-	 * @param id the id to search for
-	 * @return the <code>Pet</code> if found
-	 * @throws org.springframework.dao.DataRetrievalFailureException if not found
-	 */
-	Pet findPet(int id) throws DataAccessException;
-
-	/**
-	 * Save an <code>Owner</code> to the data store, either inserting or updating it.
-	 * @param owner the <code>Owner</code> to save
-	 * @see BaseEntity#isNew
-	 */
-	void storeOwner(Owner owner) throws DataAccessException;
-
-	/**
-	 * Save a <code>Pet</code> to the data store, either inserting or updating it.
-	 * @param pet the <code>Pet</code> to save
-	 * @see BaseEntity#isNew
-	 */
-	void storePet(Pet pet) throws DataAccessException;
-
-	/**
-	 * Save a <code>Visit</code> to the data store, either inserting or updating it.
-	 * @param visit the <code>Visit</code> to save
-	 * @see BaseEntity#isNew
-	 */
-	void storeVisit(Visit visit) throws DataAccessException;
-
-	/**
-	 * Deletes a <code>Pet</code> from the data store.
-	 */
-	void deletePet(int id) throws DataAccessException;
-
-}
diff --git a/src/main/java/org/springframework/samples/petclinic/Owner.java b/src/main/java/org/springframework/samples/petclinic/Owner.java
index 65e3df8..cb24f26 100644
--- a/src/main/java/org/springframework/samples/petclinic/Owner.java
+++ b/src/main/java/org/springframework/samples/petclinic/Owner.java
@@ -126,19 +126,12 @@ public class Owner extends Person {
 		return new ToStringCreator(this)
 
 		.append("id", this.getId())
-
 		.append("new", this.isNew())
-
 		.append("lastName", this.getLastName())
-
 		.append("firstName", this.getFirstName())
-
 		.append("address", this.address)
-
 		.append("city", this.city)
-
 		.append("telephone", this.telephone)
-
 		.toString();
 	}
 }
diff --git a/src/main/java/org/springframework/samples/petclinic/aspects/UsageLogAspect.java b/src/main/java/org/springframework/samples/petclinic/aspects/UsageLogAspect.java
index e326abf..b7fde37 100644
--- a/src/main/java/org/springframework/samples/petclinic/aspects/UsageLogAspect.java
+++ b/src/main/java/org/springframework/samples/petclinic/aspects/UsageLogAspect.java
@@ -9,7 +9,7 @@ import org.aspectj.lang.annotation.Before;
 
 /**
  * Sample AspectJ annotation-style aspect that saves
- * every owner name requested to the clinic.
+ * every owner name requested to the petRepository.
  *
  * @author Rod Johnson
  * @author Juergen Hoeller
diff --git a/src/main/java/org/springframework/samples/petclinic/jdbc/JdbcClinicImpl.java b/src/main/java/org/springframework/samples/petclinic/jdbc/JdbcClinicImpl.java
deleted file mode 100644
index ecd8cb1..0000000
--- a/src/main/java/org/springframework/samples/petclinic/jdbc/JdbcClinicImpl.java
+++ /dev/null
@@ -1,344 +0,0 @@
-package org.springframework.samples.petclinic.jdbc;
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import javax.sql.DataSource;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.dao.DataAccessException;
-import org.springframework.dao.EmptyResultDataAccessException;
-import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
-import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
-import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
-import org.springframework.jdbc.core.simple.ParameterizedBeanPropertyRowMapper;
-import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
-import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.jmx.export.annotation.ManagedOperation;
-import org.springframework.jmx.export.annotation.ManagedResource;
-import org.springframework.orm.ObjectRetrievalFailureException;
-import org.springframework.samples.petclinic.Clinic;
-import org.springframework.samples.petclinic.Owner;
-import org.springframework.samples.petclinic.Pet;
-import org.springframework.samples.petclinic.PetType;
-import org.springframework.samples.petclinic.Specialty;
-import org.springframework.samples.petclinic.Vet;
-import org.springframework.samples.petclinic.Visit;
-import org.springframework.samples.petclinic.util.EntityUtils;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-/**
- * A simple JDBC-based implementation of the {@link Clinic} interface.
- *
- * <p>This class uses Java 5 language features and the {@link SimpleJdbcTemplate}
- * plus {@link SimpleJdbcInsert}. It also takes advantage of classes like
- * {@link BeanPropertySqlParameterSource} and
- * {@link ParameterizedBeanPropertyRowMapper} which provide automatic mapping
- * between JavaBean properties and JDBC parameters or query results.
- *
- * <p>JdbcClinicImpl is a rewrite of the AbstractJdbcClinic which was the base
- * class for JDBC implementations of the Clinic interface for Spring 2.0.
- *
- * @author Ken Krebs
- * @author Juergen Hoeller
- * @author Rob Harrop
- * @author Sam Brannen
- * @author Thomas Risberg
- * @author Mark Fisher
- */
-@Service
-@ManagedResource("petclinic:type=Clinic")
-public class JdbcClinicImpl implements Clinic, JdbcClinicImplMBean {
-
-	private final Logger logger = LoggerFactory.getLogger(getClass());
-
-	private JdbcTemplate jdbcTemplate;
-	private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
-
-	private SimpleJdbcInsert insertOwner;
-	private SimpleJdbcInsert insertPet;
-	private SimpleJdbcInsert insertVisit;
-
-	private final List<Vet> vets = new ArrayList<Vet>();
-
-
-	@Autowired
-	public void init(DataSource dataSource) {
-		this.jdbcTemplate = new JdbcTemplate(dataSource);
-		this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
-
-		this.insertOwner = new SimpleJdbcInsert(dataSource)
-			.withTableName("owners")
-			.usingGeneratedKeyColumns("id");
-		this.insertPet = new SimpleJdbcInsert(dataSource)
-			.withTableName("pets")
-			.usingGeneratedKeyColumns("id");
-		this.insertVisit = new SimpleJdbcInsert(dataSource)
-			.withTableName("visits")
-			.usingGeneratedKeyColumns("id");
-	}
-
-
-	/**
-	 * Refresh the cache of Vets that the Clinic is holding.
-	 * @see org.springframework.samples.petclinic.Clinic#getVets()
-	 */
-	@ManagedOperation
-	@Transactional(readOnly = true)
-	public void refreshVetsCache() throws DataAccessException {
-		synchronized (this.vets) {
-			this.logger.info("Refreshing vets cache");
-
-			// Retrieve the list of all vets.
-			this.vets.clear();
-			this.vets.addAll(this.jdbcTemplate.query(
-					"SELECT id, first_name, last_name FROM vets ORDER BY last_name,first_name",
-					ParameterizedBeanPropertyRowMapper.newInstance(Vet.class)));
-
-			// Retrieve the list of all possible specialties.
-			final List<Specialty> specialties = this.jdbcTemplate.query(
-					"SELECT id, name FROM specialties",
-					ParameterizedBeanPropertyRowMapper.newInstance(Specialty.class));
-
-			// Build each vet's list of specialties.
-			for (Vet vet : this.vets) {
-				final List<Integer> vetSpecialtiesIds = this.jdbcTemplate.query(
-						"SELECT specialty_id FROM vet_specialties WHERE vet_id=?",
-						new ParameterizedRowMapper<Integer>() {
-							public Integer mapRow(ResultSet rs, int row) throws SQLException {
-								return Integer.valueOf(rs.getInt(1));
-							}},
-						vet.getId().intValue());
-				for (int specialtyId : vetSpecialtiesIds) {
-					Specialty specialty = EntityUtils.getById(specialties, Specialty.class, specialtyId);
-					vet.addSpecialty(specialty);
-				}
-			}
-		}
-	}
-
-
-	// START of Clinic implementation section *******************************
-
-	@Transactional(readOnly = true)
-	public Collection<Vet> getVets() throws DataAccessException {
-		synchronized (this.vets) {
-			if (this.vets.isEmpty()) {
-				refreshVetsCache();
-			}
-			return this.vets;
-		}
-	}
-
-	@Transactional(readOnly = true)
-	public Collection<PetType> getPetTypes() throws DataAccessException {
-		return this.jdbcTemplate.query(
-				"SELECT id, name FROM types ORDER BY name",
-				ParameterizedBeanPropertyRowMapper.newInstance(PetType.class));
-	}
-
-	/**
-	 * Loads {@link Owner Owners} from the data store by last name, returning
-	 * all owners whose last name <i>starts</i> with the given name; also loads
-	 * the {@link Pet Pets} and {@link Visit Visits} for the corresponding
-	 * owners, if not already loaded.
-	 */
-	@Transactional(readOnly = true)
-	public Collection<Owner> findOwners(String lastName) throws DataAccessException {
-		List<Owner> owners = this.jdbcTemplate.query(
-				"SELECT id, first_name, last_name, address, city, telephone FROM owners WHERE last_name like ?",
-				ParameterizedBeanPropertyRowMapper.newInstance(Owner.class),
-				lastName + "%");
-		loadOwnersPetsAndVisits(owners);
-		return owners;
-	}
-
-	/**
-	 * Loads the {@link Owner} with the supplied <code>id</code>; also loads
-	 * the {@link Pet Pets} and {@link Visit Visits} for the corresponding
-	 * owner, if not already loaded.
-	 */
-	@Transactional(readOnly = true)
-	public Owner findOwner(int id) throws DataAccessException {
-		Owner owner;
-		try {
-			owner = this.jdbcTemplate.queryForObject(
-					"SELECT id, first_name, last_name, address, city, telephone FROM owners WHERE id=?",
-					ParameterizedBeanPropertyRowMapper.newInstance(Owner.class),
-					id);
-		}
-		catch (EmptyResultDataAccessException ex) {
-			throw new ObjectRetrievalFailureException(Owner.class, new Integer(id));
-		}
-		loadPetsAndVisits(owner);
-		return owner;
-	}
-
-	@Transactional(readOnly = true)
-	public Pet findPet(int id) throws DataAccessException {
-		JdbcPet pet;
-		try {
-			pet = this.jdbcTemplate.queryForObject(
-					"SELECT id, name, birth_date, type_id, owner_id FROM pets WHERE id=?",
-					new JdbcPetRowMapper(),
-					id);
-		}
-		catch (EmptyResultDataAccessException ex) {
-			throw new ObjectRetrievalFailureException(Pet.class, new Integer(id));
-		}
-		Owner owner = findOwner(pet.getOwnerId());
-		owner.addPet(pet);
-		pet.setType(EntityUtils.getById(getPetTypes(), PetType.class, pet.getTypeId()));
-		loadVisits(pet);
-		return pet;
-	}
-
-	@Transactional
-	public void storeOwner(Owner owner) throws DataAccessException {
-		if (owner.isNew()) {
-			Number newKey = this.insertOwner.executeAndReturnKey(
-					new BeanPropertySqlParameterSource(owner));
-			owner.setId(newKey.intValue());
-		}
-		else {
-			this.namedParameterJdbcTemplate.update(
-					"UPDATE owners SET first_name=:firstName, last_name=:lastName, address=:address, " +
-					"city=:city, telephone=:telephone WHERE id=:id",
-					new BeanPropertySqlParameterSource(owner));
-		}
-	}
-
-	@Transactional
-	public void storePet(Pet pet) throws DataAccessException {
-		if (pet.isNew()) {
-			Number newKey = this.insertPet.executeAndReturnKey(
-					createPetParameterSource(pet));
-			pet.setId(newKey.intValue());
-		}
-		else {
-			this.namedParameterJdbcTemplate.update(
-					"UPDATE pets SET name=:name, birth_date=:birth_date, type_id=:type_id, " +
-					"owner_id=:owner_id WHERE id=:id",
-					createPetParameterSource(pet));
-		}
-	}
-
-	@Transactional
-	public void storeVisit(Visit visit) throws DataAccessException {
-		if (visit.isNew()) {
-			Number newKey = this.insertVisit.executeAndReturnKey(
-					createVisitParameterSource(visit));
-			visit.setId(newKey.intValue());
-		}
-		else {
-			throw new UnsupportedOperationException("Visit update not supported");
-		}
-	}
-
-	public void deletePet(int id) throws DataAccessException {
-		this.jdbcTemplate.update("DELETE FROM pets WHERE id=?", id);
-	}
-
-	// END of Clinic implementation section ************************************
-
-
-	/**
-	 * Creates a {@link MapSqlParameterSource} based on data values from the
-	 * supplied {@link Pet} instance.
-	 */
-	private MapSqlParameterSource createPetParameterSource(Pet pet) {
-		return new MapSqlParameterSource()
-			.addValue("id", pet.getId())
-			.addValue("name", pet.getName())
-			.addValue("birth_date", pet.getBirthDate())
-			.addValue("type_id", pet.getType().getId())
-			.addValue("owner_id", pet.getOwner().getId());
-	}
-
-	/**
-	 * Creates a {@link MapSqlParameterSource} based on data values from the
-	 * supplied {@link Visit} instance.
-	 */
-	private MapSqlParameterSource createVisitParameterSource(Visit visit) {
-		return new MapSqlParameterSource()
-			.addValue("id", visit.getId())
-			.addValue("visit_date", visit.getDate())
-			.addValue("description", visit.getDescription())
-			.addValue("pet_id", visit.getPet().getId());
-	}
-
-	/**
-	 * Loads the {@link Visit} data for the supplied {@link Pet}.
-	 */
-	private void loadVisits(JdbcPet pet) {
-		final List<Visit> visits = this.jdbcTemplate.query(
-				"SELECT id, visit_date, description FROM visits WHERE pet_id=?",
-				new ParameterizedRowMapper<Visit>() {
-					public Visit mapRow(ResultSet rs, int row) throws SQLException {
-						Visit visit = new Visit();
-						visit.setId(rs.getInt("id"));
-						visit.setDate(rs.getTimestamp("visit_date"));
-						visit.setDescription(rs.getString("description"));
-						return visit;
-					}
-				},
-				pet.getId().intValue());
-		for (Visit visit : visits) {
-			pet.addVisit(visit);
-		}
-	}
-
-	/**
-	 * Loads the {@link Pet} and {@link Visit} data for the supplied
-	 * {@link Owner}.
-	 */
-	private void loadPetsAndVisits(final Owner owner) {
-		final List<JdbcPet> pets = this.jdbcTemplate.query(
-				"SELECT id, name, birth_date, type_id, owner_id FROM pets WHERE owner_id=?",
-				new JdbcPetRowMapper(),
-				owner.getId().intValue());
-		for (JdbcPet pet : pets) {
-			owner.addPet(pet);
-			pet.setType(EntityUtils.getById(getPetTypes(), PetType.class, pet.getTypeId()));
-			loadVisits(pet);
-		}
-	}
-
-	/**
-	 * Loads the {@link Pet} and {@link Visit} data for the supplied
-	 * {@link List} of {@link Owner Owners}.
-	 *
-	 * @param owners the list of owners for whom the pet and visit data should be loaded
-	 * @see #loadPetsAndVisits(Owner)
-	 */
-	private void loadOwnersPetsAndVisits(List<Owner> owners) {
-		for (Owner owner : owners) {
-			loadPetsAndVisits(owner);
-		}
-	}
-
-	/**
-	 * {@link ParameterizedRowMapper} implementation mapping data from a
-	 * {@link ResultSet} to the corresponding properties of the {@link JdbcPet} class.
-	 */
-	private class JdbcPetRowMapper implements ParameterizedRowMapper<JdbcPet> {
-
-		public JdbcPet mapRow(ResultSet rs, int rownum) throws SQLException {
-			JdbcPet pet = new JdbcPet();
-			pet.setId(rs.getInt("id"));
-			pet.setName(rs.getString("name"));
-			pet.setBirthDate(rs.getDate("birth_date"));
-			pet.setTypeId(rs.getInt("type_id"));
-			pet.setOwnerId(rs.getInt("owner_id"));
-			return pet;
-		}
-	}
-
-}
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java b/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java
new file mode 100644
index 0000000..4a24d54
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java
@@ -0,0 +1,47 @@
+package org.springframework.samples.petclinic.repository;
+
+import java.util.Collection;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.samples.petclinic.BaseEntity;
+import org.springframework.samples.petclinic.Owner;
+
+/**
+ * The high-level PetClinic business interface.
+ *
+ * <p>This is basically a data access object.
+ * PetClinic doesn't have a dedicated business facade.
+ *
+ * @author Ken Krebs
+ * @author Juergen Hoeller
+ * @author Sam Brannen
+ */ 
+public interface OwnerRepository {
+
+	/**
+	 * Retrieve <code>Owner</code>s from the data store by last name,
+	 * returning all owners whose last name <i>starts</i> with the given name.
+	 * @param lastName Value to search for
+	 * @return a <code>Collection</code> of matching <code>Owner</code>s
+	 * (or an empty <code>Collection</code> if none found)
+	 */
+	Collection<Owner> findByLastName(String lastName) throws DataAccessException;
+
+	/**
+	 * Retrieve an <code>Owner</code> from the data store by id.
+	 * @param id the id to search for
+	 * @return the <code>Owner</code> if found
+	 * @throws org.springframework.dao.DataRetrievalFailureException if not found
+	 */
+	Owner findById(int id) throws DataAccessException;
+
+
+	/**
+	 * Save an <code>Owner</code> to the data store, either inserting or updating it.
+	 * @param owner the <code>Owner</code> to save
+	 * @see BaseEntity#isNew
+	 */
+	void save(Owner owner) throws DataAccessException;
+
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/PetRepository.java b/src/main/java/org/springframework/samples/petclinic/repository/PetRepository.java
new file mode 100644
index 0000000..119e0e3
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/repository/PetRepository.java
@@ -0,0 +1,51 @@
+package org.springframework.samples.petclinic.repository;
+
+import java.util.Collection;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.samples.petclinic.BaseEntity;
+import org.springframework.samples.petclinic.Owner;
+import org.springframework.samples.petclinic.Pet;
+import org.springframework.samples.petclinic.PetType;
+import org.springframework.samples.petclinic.Vet;
+import org.springframework.samples.petclinic.Visit;
+
+/**
+ * The high-level PetClinic business interface.
+ *
+ * <p>This is basically a data access object.
+ * PetClinic doesn't have a dedicated business facade.
+ *
+ * @author Ken Krebs
+ * @author Juergen Hoeller
+ * @author Sam Brannen
+ */
+public interface PetRepository {
+
+	/**
+	 * Retrieve all <code>PetType</code>s from the data store.
+	 * @return a <code>Collection</code> of <code>PetType</code>s
+	 */
+	Collection<PetType> getPetTypes() throws DataAccessException;
+
+	/**
+	 * Retrieve a <code>Pet</code> from the data store by id.
+	 * @param id the id to search for
+	 * @return the <code>Pet</code> if found
+	 * @throws org.springframework.dao.DataRetrievalFailureException if not found
+	 */
+	Pet findById(int id) throws DataAccessException;
+
+	/**
+	 * Save a <code>Pet</code> to the data store, either inserting or updating it.
+	 * @param pet the <code>Pet</code> to save
+	 * @see BaseEntity#isNew
+	 */
+	void storePet(Pet pet) throws DataAccessException;
+
+	/**
+	 * Deletes a <code>Pet</code> from the data store.
+	 */
+	void deletePet(int id) throws DataAccessException;
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/VetRepository.java b/src/main/java/org/springframework/samples/petclinic/repository/VetRepository.java
new file mode 100644
index 0000000..a306860
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/repository/VetRepository.java
@@ -0,0 +1,27 @@
+package org.springframework.samples.petclinic.repository;
+
+import java.util.Collection;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.samples.petclinic.Vet;
+
+/**
+ * The high-level PetClinic business interface.
+ *
+ * <p>This is basically a data access object.
+ * PetClinic doesn't have a dedicated business facade.
+ *
+ * @author Ken Krebs
+ * @author Juergen Hoeller
+ * @author Sam Brannen
+ */
+public interface VetRepository {
+
+	/**
+	 * Retrieve all <code>Vet</code>s from the data store.
+	 * @return a <code>Collection</code> of <code>Vet</code>s
+	 */
+	Collection<Vet> getVets() throws DataAccessException;
+
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/VisitRepository.java b/src/main/java/org/springframework/samples/petclinic/repository/VisitRepository.java
new file mode 100644
index 0000000..2af5ac7
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/repository/VisitRepository.java
@@ -0,0 +1,30 @@
+package org.springframework.samples.petclinic.repository;
+
+import java.util.List;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.samples.petclinic.BaseEntity;
+import org.springframework.samples.petclinic.Visit;
+
+/**
+ * The high-level PetClinic business interface.
+ *
+ * <p>This is basically a data access object.
+ * PetClinic doesn't have a dedicated business facade.
+ *
+ * @author Ken Krebs
+ * @author Juergen Hoeller
+ * @author Sam Brannen
+ */
+public interface VisitRepository {
+
+	/**
+	 * Save a <code>Visit</code> to the data store, either inserting or updating it.
+	 * @param visit the <code>Visit</code> to save
+	 * @see BaseEntity#isNew
+	 */
+	void storeVisit(Visit visit) throws DataAccessException;
+
+	List<Visit> findByPetId(Integer petId);
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/jdbc/JdbcClinicImplMBean.java b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcClinicImplMBean.java
similarity index 59%
rename from src/main/java/org/springframework/samples/petclinic/jdbc/JdbcClinicImplMBean.java
rename to src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcClinicImplMBean.java
index 6eaa97c..b324036 100644
--- a/src/main/java/org/springframework/samples/petclinic/jdbc/JdbcClinicImplMBean.java
+++ b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcClinicImplMBean.java
@@ -1,4 +1,4 @@
-package org.springframework.samples.petclinic.jdbc;
+package org.springframework.samples.petclinic.repository.jdbc;
 
 /**
  * Interface that defines a cache refresh operation.
@@ -11,8 +11,8 @@ package org.springframework.samples.petclinic.jdbc;
 public interface JdbcClinicImplMBean {
 
 	/**
-	 * Refresh the cache of Vets that the Clinic is holding.
-	 * @see org.springframework.samples.petclinic.Clinic#getVets()
+	 * Refresh the cache of Vets that the ClinicService is holding.
+	 * @see org.springframework.samples.petclinic.service.ClinicService#getVets()
 	 * @see JdbcClinicImpl#refreshVetsCache()
 	 */
 	void refreshVetsCache();
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcOwnerRepositoryImpl.java b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcOwnerRepositoryImpl.java
new file mode 100644
index 0000000..eef9dfd
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcOwnerRepositoryImpl.java
@@ -0,0 +1,173 @@
+package org.springframework.samples.petclinic.repository.jdbc;
+
+import java.util.Collection;
+import java.util.List;
+
+import javax.sql.DataSource;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.jdbc.core.simple.ParameterizedBeanPropertyRowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
+import org.springframework.orm.ObjectRetrievalFailureException;
+import org.springframework.samples.petclinic.Owner;
+import org.springframework.samples.petclinic.Pet;
+import org.springframework.samples.petclinic.PetType;
+import org.springframework.samples.petclinic.Visit;
+import org.springframework.samples.petclinic.repository.OwnerRepository;
+import org.springframework.samples.petclinic.repository.PetRepository;
+import org.springframework.samples.petclinic.repository.VisitRepository;
+import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.samples.petclinic.util.EntityUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * A simple JDBC-based implementation of the {@link ClinicService} interface.
+ *
+ * <p>This class uses Java 5 language features and the {@link SimpleJdbcTemplate}
+ * plus {@link SimpleJdbcInsert}. It also takes advantage of classes like
+ * {@link BeanPropertySqlParameterSource} and
+ * {@link ParameterizedBeanPropertyRowMapper} which provide automatic mapping
+ * between JavaBean properties and JDBC parameters or query results.
+ *
+ * <p>JdbcClinicImpl is a rewrite of the AbstractJdbcClinic which was the base
+ * class for JDBC implementations of the ClinicService interface for Spring 2.0.
+ *
+ * @author Ken Krebs
+ * @author Juergen Hoeller
+ * @author Rob Harrop
+ * @author Sam Brannen
+ * @author Thomas Risberg
+ * @author Mark Fisher
+ */
+@Service
+public class JdbcOwnerRepositoryImpl implements OwnerRepository {
+
+	@Autowired
+	private PetRepository petRepository;
+	
+	@Autowired
+	private VisitRepository visitRepository;
+	
+	@Autowired
+	private JdbcTemplate jdbcTemplate;
+	
+	@Autowired
+	private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
+
+	private SimpleJdbcInsert insertOwner;
+
+	@Autowired
+	public void init(DataSource dataSource) {
+
+		this.insertOwner = new SimpleJdbcInsert(dataSource)
+			.withTableName("owners")
+			.usingGeneratedKeyColumns("id");
+	}
+
+
+	
+
+	/**
+	 * Loads {@link Owner Owners} from the data store by last name, returning
+	 * all owners whose last name <i>starts</i> with the given name; also loads
+	 * the {@link Pet Pets} and {@link Visit Visits} for the corresponding
+	 * owners, if not already loaded.
+	 */
+	@Transactional(readOnly = true)
+	public Collection<Owner> findByLastName(String lastName) throws DataAccessException {
+		List<Owner> owners = this.jdbcTemplate.query(
+				"SELECT id, first_name, last_name, address, city, telephone FROM owners WHERE last_name like ?",
+				ParameterizedBeanPropertyRowMapper.newInstance(Owner.class),
+				lastName + "%");
+		loadOwnersPetsAndVisits(owners);
+		return owners;
+	}
+
+	/**
+	 * Loads the {@link Owner} with the supplied <code>id</code>; also loads
+	 * the {@link Pet Pets} and {@link Visit Visits} for the corresponding
+	 * owner, if not already loaded.
+	 */
+	@Transactional(readOnly = true)
+	public Owner findById(int id) throws DataAccessException {
+		Owner owner;
+		try {
+			owner = this.jdbcTemplate.queryForObject(
+					"SELECT id, first_name, last_name, address, city, telephone FROM owners WHERE id=?",
+					ParameterizedBeanPropertyRowMapper.newInstance(Owner.class),
+					id);
+		}
+		catch (EmptyResultDataAccessException ex) {
+			throw new ObjectRetrievalFailureException(Owner.class, new Integer(id));
+		}
+		loadPetsAndVisits(owner);
+		return owner;
+	}
+	
+	public void loadPetsAndVisits(final Owner owner) {
+		final List<JdbcPet> pets = this.jdbcTemplate.query(
+				"SELECT id, name, birth_date, type_id, owner_id FROM pets WHERE owner_id=?",
+				new JdbcPetRowMapper(),
+				owner.getId().intValue());
+		for (JdbcPet pet : pets) {
+			owner.addPet(pet);
+			pet.setType(EntityUtils.getById(getPetTypes(), PetType.class, pet.getTypeId()));
+			List<Visit> visits = this.visitRepository.findByPetId(pet.getId());
+			for (Visit visit : visits) {
+				pet.addVisit(visit);
+			}
+		}
+	}
+
+	
+
+	@Transactional
+	public void save(Owner owner) throws DataAccessException {
+		if (owner.isNew()) {
+			Number newKey = this.insertOwner.executeAndReturnKey(
+					new BeanPropertySqlParameterSource(owner));
+			owner.setId(newKey.intValue());
+		}
+		else {
+			this.namedParameterJdbcTemplate.update(
+					"UPDATE owners SET first_name=:firstName, last_name=:lastName, address=:address, " +
+					"city=:city, telephone=:telephone WHERE id=:id",
+					new BeanPropertySqlParameterSource(owner));
+		}
+	}
+
+	
+
+
+	
+	@Transactional(readOnly = true)
+	public Collection<PetType> getPetTypes() throws DataAccessException {
+		return this.jdbcTemplate.query(
+				"SELECT id, name FROM types ORDER BY name",
+				ParameterizedBeanPropertyRowMapper.newInstance(PetType.class));
+	}
+
+	/**
+	 * Loads the {@link Pet} and {@link Visit} data for the supplied
+	 * {@link List} of {@link Owner Owners}.
+	 *
+	 * @param owners the list of owners for whom the pet and visit data should be loaded
+	 * @see #loadPetsAndVisits(Owner)
+	 */
+	private void loadOwnersPetsAndVisits(List<Owner> owners) {
+		for (Owner owner : owners) {
+			loadPetsAndVisits(owner);
+		}
+	}
+
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/jdbc/JdbcPet.java b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcPet.java
similarity index 78%
rename from src/main/java/org/springframework/samples/petclinic/jdbc/JdbcPet.java
rename to src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcPet.java
index aa0bf18..4a9ccf3 100644
--- a/src/main/java/org/springframework/samples/petclinic/jdbc/JdbcPet.java
+++ b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcPet.java
@@ -1,10 +1,10 @@
-package org.springframework.samples.petclinic.jdbc;
+package org.springframework.samples.petclinic.repository.jdbc;
 
 import org.springframework.samples.petclinic.Pet;
 
 /**
  * Subclass of Pet that carries temporary id properties which
- * are only relevant for a JDBC implmentation of the Clinic.
+ * are only relevant for a JDBC implmentation of the ClinicService.
  *
  * @author Juergen Hoeller
  * @see JdbcClinicImpl
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcPetRepositoryImpl.java b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcPetRepositoryImpl.java
new file mode 100644
index 0000000..6efff5f
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcPetRepositoryImpl.java
@@ -0,0 +1,160 @@
+package org.springframework.samples.petclinic.repository.jdbc;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.sql.DataSource;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.jdbc.core.simple.ParameterizedBeanPropertyRowMapper;
+import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jmx.export.annotation.ManagedOperation;
+import org.springframework.jmx.export.annotation.ManagedResource;
+import org.springframework.orm.ObjectRetrievalFailureException;
+import org.springframework.samples.petclinic.Owner;
+import org.springframework.samples.petclinic.Pet;
+import org.springframework.samples.petclinic.PetType;
+import org.springframework.samples.petclinic.Specialty;
+import org.springframework.samples.petclinic.Vet;
+import org.springframework.samples.petclinic.Visit;
+import org.springframework.samples.petclinic.repository.OwnerRepository;
+import org.springframework.samples.petclinic.repository.PetRepository;
+import org.springframework.samples.petclinic.repository.VisitRepository;
+import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.samples.petclinic.util.EntityUtils;
+import org.springframework.stereotype.Repository;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * A simple JDBC-based implementation of the {@link ClinicService} interface.
+ *
+ * <p>This class uses Java 5 language features and the {@link SimpleJdbcTemplate}
+ * plus {@link SimpleJdbcInsert}. It also takes advantage of classes like
+ * {@link BeanPropertySqlParameterSource} and
+ * {@link ParameterizedBeanPropertyRowMapper} which provide automatic mapping
+ * between JavaBean properties and JDBC parameters or query results.
+ *
+ * <p>JdbcClinicImpl is a rewrite of the AbstractJdbcClinic which was the base
+ * class for JDBC implementations of the ClinicService interface for Spring 2.0.
+ *
+ * @author Ken Krebs
+ * @author Juergen Hoeller
+ * @author Rob Harrop
+ * @author Sam Brannen
+ * @author Thomas Risberg
+ * @author Mark Fisher
+ */
+@Repository
+public class JdbcPetRepositoryImpl implements PetRepository {
+
+	private JdbcTemplate jdbcTemplate;
+	private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
+
+	private SimpleJdbcInsert insertPet;
+	
+	@Autowired
+	private OwnerRepository ownerRepository;
+	
+	@Autowired
+	private VisitRepository visitRepository;
+
+	private final List<Vet> vets = new ArrayList<Vet>();
+
+
+	@Autowired
+	public void init(DataSource dataSource) {
+		this.jdbcTemplate = new JdbcTemplate(dataSource);
+		this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
+
+		this.insertPet = new SimpleJdbcInsert(dataSource)
+			.withTableName("pets")
+			.usingGeneratedKeyColumns("id");
+	}
+
+	@Transactional(readOnly = true)
+	public Collection<PetType> getPetTypes() throws DataAccessException {
+		return this.jdbcTemplate.query(
+				"SELECT id, name FROM types ORDER BY name",
+				ParameterizedBeanPropertyRowMapper.newInstance(PetType.class));
+	}
+
+	@Transactional(readOnly = true)
+	public Pet findById(int id) throws DataAccessException {
+		JdbcPet pet;
+		try {
+			pet = this.jdbcTemplate.queryForObject(
+					"SELECT id, name, birth_date, type_id, owner_id FROM pets WHERE id=?",
+					new JdbcPetRowMapper(),
+					id);
+		}
+		catch (EmptyResultDataAccessException ex) {
+			throw new ObjectRetrievalFailureException(Pet.class, new Integer(id));
+		}
+		Owner owner = this.ownerRepository.findById(pet.getOwnerId());
+		owner.addPet(pet);
+		pet.setType(EntityUtils.getById(getPetTypes(), PetType.class, pet.getTypeId()));
+		
+		List<Visit> visits = this.visitRepository.findByPetId(pet.getId());
+		for (Visit visit : visits) {
+			pet.addVisit(visit);
+		}
+		return pet;
+	}
+
+	@Transactional
+	public void storePet(Pet pet) throws DataAccessException {
+		if (pet.isNew()) {
+			Number newKey = this.insertPet.executeAndReturnKey(
+					createPetParameterSource(pet));
+			pet.setId(newKey.intValue());
+		}
+		else {
+			this.namedParameterJdbcTemplate.update(
+					"UPDATE pets SET name=:name, birth_date=:birth_date, type_id=:type_id, " +
+					"owner_id=:owner_id WHERE id=:id",
+					createPetParameterSource(pet));
+		}
+	}
+
+	/**
+	 * Creates a {@link MapSqlParameterSource} based on data values from the
+	 * supplied {@link Pet} instance.
+	 */
+	private MapSqlParameterSource createPetParameterSource(Pet pet) {
+		return new MapSqlParameterSource()
+			.addValue("id", pet.getId())
+			.addValue("name", pet.getName())
+			.addValue("birth_date", pet.getBirthDate())
+			.addValue("type_id", pet.getType().getId())
+			.addValue("owner_id", pet.getOwner().getId());
+	}
+
+	@Override
+	public void deletePet(int id) throws DataAccessException {
+		// TODO Auto-generated method stub
+		
+	}
+
+
+	/**
+	 * Loads the {@link Pet} and {@link Visit} data for the supplied
+	 * {@link Owner}.
+	 */
+
+
+
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcPetRowMapper.java b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcPetRowMapper.java
new file mode 100644
index 0000000..575f460
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcPetRowMapper.java
@@ -0,0 +1,23 @@
+package org.springframework.samples.petclinic.repository.jdbc;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
+
+/**
+ * {@link ParameterizedRowMapper} implementation mapping data from a
+ * {@link ResultSet} to the corresponding properties of the {@link JdbcPet} class.
+ */
+class JdbcPetRowMapper implements ParameterizedRowMapper<JdbcPet> {
+
+	public JdbcPet mapRow(ResultSet rs, int rownum) throws SQLException {
+		JdbcPet pet = new JdbcPet();
+		pet.setId(rs.getInt("id"));
+		pet.setName(rs.getString("name"));
+		pet.setBirthDate(rs.getDate("birth_date"));
+		pet.setTypeId(rs.getInt("type_id"));
+		pet.setOwnerId(rs.getInt("owner_id"));
+		return pet;
+	}
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVetRepositoryImpl.java b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVetRepositoryImpl.java
new file mode 100644
index 0000000..88b8c03
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVetRepositoryImpl.java
@@ -0,0 +1,118 @@
+package org.springframework.samples.petclinic.repository.jdbc;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.sql.DataSource;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.jdbc.core.simple.ParameterizedBeanPropertyRowMapper;
+import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jmx.export.annotation.ManagedOperation;
+import org.springframework.jmx.export.annotation.ManagedResource;
+import org.springframework.orm.ObjectRetrievalFailureException;
+import org.springframework.samples.petclinic.Owner;
+import org.springframework.samples.petclinic.Pet;
+import org.springframework.samples.petclinic.PetType;
+import org.springframework.samples.petclinic.Specialty;
+import org.springframework.samples.petclinic.Vet;
+import org.springframework.samples.petclinic.Visit;
+import org.springframework.samples.petclinic.repository.VetRepository;
+import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.samples.petclinic.util.EntityUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * A simple JDBC-based implementation of the {@link ClinicService} interface.
+ *
+ * <p>This class uses Java 5 language features and the {@link SimpleJdbcTemplate}
+ * plus {@link SimpleJdbcInsert}. It also takes advantage of classes like
+ * {@link BeanPropertySqlParameterSource} and
+ * {@link ParameterizedBeanPropertyRowMapper} which provide automatic mapping
+ * between JavaBean properties and JDBC parameters or query results.
+ *
+ * <p>JdbcClinicImpl is a rewrite of the AbstractJdbcClinic which was the base
+ * class for JDBC implementations of the ClinicService interface for Spring 2.0.
+ *
+ * @author Ken Krebs
+ * @author Juergen Hoeller
+ * @author Rob Harrop
+ * @author Sam Brannen
+ * @author Thomas Risberg
+ * @author Mark Fisher
+ */
+@Service
+public class JdbcVetRepositoryImpl implements VetRepository {
+
+	private final Logger logger = LoggerFactory.getLogger(getClass());
+
+	@Autowired
+	private JdbcTemplate jdbcTemplate;
+
+	private final List<Vet> vets = new ArrayList<Vet>();
+
+
+
+	/**
+	 * Refresh the cache of Vets that the ClinicService is holding.
+	 * @see org.springframework.samples.petclinic.service.ClinicService#getVets()
+	 */
+	@ManagedOperation
+	@Transactional(readOnly = true)
+	public void refreshVetsCache() throws DataAccessException {
+		synchronized (this.vets) {
+			this.logger.info("Refreshing vets cache");
+
+			// Retrieve the list of all vets.
+			this.vets.clear();
+			this.vets.addAll(this.jdbcTemplate.query(
+					"SELECT id, first_name, last_name FROM vets ORDER BY last_name,first_name",
+					ParameterizedBeanPropertyRowMapper.newInstance(Vet.class)));
+
+			// Retrieve the list of all possible specialties.
+			final List<Specialty> specialties = this.jdbcTemplate.query(
+					"SELECT id, name FROM specialties",
+					ParameterizedBeanPropertyRowMapper.newInstance(Specialty.class));
+
+			// Build each vet's list of specialties.
+			for (Vet vet : this.vets) {
+				final List<Integer> vetSpecialtiesIds = this.jdbcTemplate.query(
+						"SELECT specialty_id FROM vet_specialties WHERE vet_id=?",
+						new ParameterizedRowMapper<Integer>() {
+							public Integer mapRow(ResultSet rs, int row) throws SQLException {
+								return Integer.valueOf(rs.getInt(1));
+							}},
+						vet.getId().intValue());
+				for (int specialtyId : vetSpecialtiesIds) {
+					Specialty specialty = EntityUtils.getById(specialties, Specialty.class, specialtyId);
+					vet.addSpecialty(specialty);
+				}
+			}
+		}
+	}
+
+	@Transactional(readOnly = true)
+	public Collection<Vet> getVets() throws DataAccessException {
+		synchronized (this.vets) {
+			if (this.vets.isEmpty()) {
+				refreshVetsCache();
+			}
+			return this.vets;
+		}
+	}
+
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVisitRepositoryImpl.java b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVisitRepositoryImpl.java
new file mode 100644
index 0000000..f1cc60b
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVisitRepositoryImpl.java
@@ -0,0 +1,131 @@
+package org.springframework.samples.petclinic.repository.jdbc;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+
+import javax.sql.DataSource;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+import org.springframework.jdbc.core.simple.ParameterizedBeanPropertyRowMapper;
+import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
+import org.springframework.samples.petclinic.Pet;
+import org.springframework.samples.petclinic.Visit;
+import org.springframework.samples.petclinic.repository.VisitRepository;
+import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * A simple JDBC-based implementation of the {@link ClinicService} interface.
+ *
+ * <p>This class uses Java 5 language features and the {@link SimpleJdbcTemplate}
+ * plus {@link SimpleJdbcInsert}. It also takes advantage of classes like
+ * {@link BeanPropertySqlParameterSource} and
+ * {@link ParameterizedBeanPropertyRowMapper} which provide automatic mapping
+ * between JavaBean properties and JDBC parameters or query results.
+ *
+ * <p>JdbcClinicImpl is a rewrite of the AbstractJdbcClinic which was the base
+ * class for JDBC implementations of the ClinicService interface for Spring 2.0.
+ *
+ * @author Ken Krebs
+ * @author Juergen Hoeller
+ * @author Rob Harrop
+ * @author Sam Brannen
+ * @author Thomas Risberg
+ * @author Mark Fisher
+ */
+@Service
+public class JdbcVisitRepositoryImpl implements VisitRepository {
+
+	private JdbcTemplate jdbcTemplate;
+
+	private SimpleJdbcInsert insertVisit;
+
+	@Autowired
+	public void init(DataSource dataSource) {
+		this.jdbcTemplate = new JdbcTemplate(dataSource);
+
+		this.insertVisit = new SimpleJdbcInsert(dataSource)
+			.withTableName("visits")
+			.usingGeneratedKeyColumns("id");
+	}
+
+
+	@Transactional
+	public void storeVisit(Visit visit) throws DataAccessException {
+		if (visit.isNew()) {
+			Number newKey = this.insertVisit.executeAndReturnKey(
+					createVisitParameterSource(visit));
+			visit.setId(newKey.intValue());
+		}
+		else {
+			throw new UnsupportedOperationException("Visit update not supported");
+		}
+	}
+
+	public void deletePet(int id) throws DataAccessException {
+		this.jdbcTemplate.update("DELETE FROM pets WHERE id=?", id);
+	}
+
+	// END of ClinicService implementation section ************************************
+
+
+	/**
+	 * Creates a {@link MapSqlParameterSource} based on data values from the
+	 * supplied {@link Visit} instance.
+	 */
+	private MapSqlParameterSource createVisitParameterSource(Visit visit) {
+		return new MapSqlParameterSource()
+			.addValue("id", visit.getId())
+			.addValue("visit_date", visit.getDate())
+			.addValue("description", visit.getDescription())
+			.addValue("pet_id", visit.getPet().getId());
+	}
+
+
+
+	@Override
+	public List<Visit> findByPetId(Integer petId) {
+		final List<Visit> visits = this.jdbcTemplate.query(
+				"SELECT id, visit_date, description FROM visits WHERE pet_id=?",
+				new ParameterizedRowMapper<Visit>() {
+					public Visit mapRow(ResultSet rs, int row) throws SQLException {
+						Visit visit = new Visit();
+						visit.setId(rs.getInt("id"));
+						visit.setDate(rs.getTimestamp("visit_date"));
+						visit.setDescription(rs.getString("description"));
+						return visit;
+					}
+				},
+				petId);
+		return visits;
+	}
+	
+	 
+
+	/**
+	 * {@link ParameterizedRowMapper} implementation mapping data from a
+	 * {@link ResultSet} to the corresponding properties of the {@link JdbcPet} class.
+	 */
+	private class JdbcPetRowMapper implements ParameterizedRowMapper<JdbcPet> {
+
+		public JdbcPet mapRow(ResultSet rs, int rownum) throws SQLException {
+			JdbcPet pet = new JdbcPet();
+			pet.setId(rs.getInt("id"));
+			pet.setName(rs.getString("name"));
+			pet.setBirthDate(rs.getDate("birth_date"));
+			pet.setTypeId(rs.getInt("type_id"));
+			pet.setOwnerId(rs.getInt("owner_id"));
+			return pet;
+		}
+	}
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/jdbc/package-info.java b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/package-info.java
similarity index 62%
rename from src/main/java/org/springframework/samples/petclinic/jdbc/package-info.java
rename to src/main/java/org/springframework/samples/petclinic/repository/jdbc/package-info.java
index 6ec278b..edd0bf8 100644
--- a/src/main/java/org/springframework/samples/petclinic/jdbc/package-info.java
+++ b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/package-info.java
@@ -5,5 +5,5 @@
  * of PetClinic's persistence layer.
  *
  */
-package org.springframework.samples.petclinic.jdbc;
+package org.springframework.samples.petclinic.repository.jdbc;
 
diff --git a/src/main/java/org/springframework/samples/petclinic/jpa/JpaClinicImpl.java b/src/main/java/org/springframework/samples/petclinic/repository/jpa/JpaClinicImpl.java
similarity index 89%
rename from src/main/java/org/springframework/samples/petclinic/jpa/JpaClinicImpl.java
rename to src/main/java/org/springframework/samples/petclinic/repository/jpa/JpaClinicImpl.java
index 4d19897..361fd4b 100644
--- a/src/main/java/org/springframework/samples/petclinic/jpa/JpaClinicImpl.java
+++ b/src/main/java/org/springframework/samples/petclinic/repository/jpa/JpaClinicImpl.java
@@ -1,4 +1,4 @@
-package org.springframework.samples.petclinic.jpa;
+package org.springframework.samples.petclinic.repository.jpa;
 
 import java.util.Collection;
 
@@ -6,18 +6,18 @@ import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
 import javax.persistence.Query;
 
-import org.springframework.samples.petclinic.Clinic;
 import org.springframework.samples.petclinic.Owner;
 import org.springframework.samples.petclinic.Pet;
 import org.springframework.samples.petclinic.PetType;
 import org.springframework.samples.petclinic.Vet;
 import org.springframework.samples.petclinic.Visit;
+import org.springframework.samples.petclinic.service.ClinicService;
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.dao.DataAccessException;
 
 /**
- * JPA implementation of the Clinic interface using EntityManager.
+ * JPA implementation of the ClinicService interface using EntityManager.
  *
  * <p>The mappings are defined in "orm.xml" located in the META-INF directory.
  *
@@ -29,7 +29,7 @@ import org.springframework.dao.DataAccessException;
  */
 @Repository
 @Transactional
-public class JpaClinicImpl implements Clinic {
+public class JpaClinicImpl implements ClinicService {
 
 	@PersistenceContext
 	private EntityManager em;
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/jpa/JpaOwnerRepositoryImpl.java b/src/main/java/org/springframework/samples/petclinic/repository/jpa/JpaOwnerRepositoryImpl.java
new file mode 100644
index 0000000..73ee82a
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/repository/jpa/JpaOwnerRepositoryImpl.java
@@ -0,0 +1,57 @@
+package org.springframework.samples.petclinic.repository.jpa;
+
+import java.util.Collection;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.samples.petclinic.Owner;
+import org.springframework.samples.petclinic.Pet;
+import org.springframework.samples.petclinic.PetType;
+import org.springframework.samples.petclinic.Vet;
+import org.springframework.samples.petclinic.Visit;
+import org.springframework.samples.petclinic.repository.OwnerRepository;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * JPA implementation of the ClinicService interface using EntityManager.
+ *
+ * <p>The mappings are defined in "orm.xml" located in the META-INF directory.
+ *
+ * @author Mike Keith
+ * @author Rod Johnson
+ * @author Sam Brannen
+ * @author Michael Isvy
+ * @since 22.4.2006
+ */
+@Repository
+@Transactional
+public class JpaOwnerRepositoryImpl implements OwnerRepository {
+
+	@PersistenceContext
+	private EntityManager em;
+
+
+	@Transactional(readOnly = true)
+	@SuppressWarnings("unchecked")
+	public Collection<Owner> findByLastName(String lastName) {
+		Query query = this.em.createQuery("SELECT owner FROM Owner owner WHERE owner.lastName LIKE :lastName");
+		query.setParameter("lastName", lastName + "%");
+		return query.getResultList();
+	}
+
+	@Transactional(readOnly = true)
+	public Owner findById(int id) {
+		return this.em.find(Owner.class, id);
+	}
+
+
+	public void save(Owner owner) {
+		this.em.merge(owner);
+
+	}
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/jpa/SpringDataClinic.java b/src/main/java/org/springframework/samples/petclinic/repository/jpa/SpringDataClinic.java
similarity index 83%
rename from src/main/java/org/springframework/samples/petclinic/jpa/SpringDataClinic.java
rename to src/main/java/org/springframework/samples/petclinic/repository/jpa/SpringDataClinic.java
index f21a576..cf1af4b 100644
--- a/src/main/java/org/springframework/samples/petclinic/jpa/SpringDataClinic.java
+++ b/src/main/java/org/springframework/samples/petclinic/repository/jpa/SpringDataClinic.java
@@ -1,22 +1,22 @@
-package org.springframework.samples.petclinic.jpa;
+package org.springframework.samples.petclinic.repository.jpa;
 
 import java.util.Collection;
 
 import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.Repository;
-import org.springframework.samples.petclinic.Clinic;
 import org.springframework.samples.petclinic.Owner;
 import org.springframework.samples.petclinic.Pet;
 import org.springframework.samples.petclinic.PetType;
 import org.springframework.samples.petclinic.Vet;
 import org.springframework.samples.petclinic.Visit;
+import org.springframework.samples.petclinic.service.ClinicService;
 
 /**
  *
  * @author Michael Isvy
  * @since 15.1.2013
  */
-public interface SpringDataClinic extends Clinic, Repository {
+public interface SpringDataClinic extends ClinicService, Repository {
 
 
 
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/jpa/SpringDataOwnerRepository.java b/src/main/java/org/springframework/samples/petclinic/repository/jpa/SpringDataOwnerRepository.java
new file mode 100644
index 0000000..f32b34c
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/repository/jpa/SpringDataOwnerRepository.java
@@ -0,0 +1,13 @@
+package org.springframework.samples.petclinic.repository.jpa;
+
+import org.springframework.data.repository.Repository;
+import org.springframework.samples.petclinic.Owner;
+import org.springframework.samples.petclinic.repository.OwnerRepository;
+
+/**
+ *
+ * @author Michael Isvy
+ * @since 15.1.2013
+ */
+public interface SpringDataOwnerRepository extends OwnerRepository, Repository<Owner, Integer> {
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/jpa/package-info.java b/src/main/java/org/springframework/samples/petclinic/repository/jpa/package-info.java
similarity index 62%
rename from src/main/java/org/springframework/samples/petclinic/jpa/package-info.java
rename to src/main/java/org/springframework/samples/petclinic/repository/jpa/package-info.java
index 8093784..13c8552 100644
--- a/src/main/java/org/springframework/samples/petclinic/jpa/package-info.java
+++ b/src/main/java/org/springframework/samples/petclinic/repository/jpa/package-info.java
@@ -5,5 +5,5 @@
  * of PetClinic's persistence layer.
  *
  */
-package org.springframework.samples.petclinic.jpa;
+package org.springframework.samples.petclinic.repository.jpa;
 
diff --git a/src/main/java/org/springframework/samples/petclinic/service/ClinicService.java b/src/main/java/org/springframework/samples/petclinic/service/ClinicService.java
new file mode 100644
index 0000000..24a9329
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/service/ClinicService.java
@@ -0,0 +1,39 @@
+package org.springframework.samples.petclinic.service;
+
+import java.util.Collection;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.samples.petclinic.Owner;
+import org.springframework.samples.petclinic.Pet;
+import org.springframework.samples.petclinic.PetType;
+import org.springframework.samples.petclinic.Vet;
+import org.springframework.samples.petclinic.Visit;
+
+
+/**
+ * The high-level PetClinic business interface.
+ *
+ * <p>This is basically a data access object.
+ * PetClinic doesn't have a dedicated business facade.
+ *
+ * @author Ken Krebs
+ * @author Juergen Hoeller
+ * @author Sam Brannen
+ */
+public interface ClinicService {
+	
+	public Collection<PetType> getPetTypes() throws DataAccessException;
+	
+	public Owner findOwnerById(int id) throws DataAccessException;
+	
+	public Pet findPetById(int id) throws DataAccessException;
+
+	public void storePet(Pet pet) throws DataAccessException;
+
+	public void deletePet(int id) throws DataAccessException;
+	
+	public void storeVisit(Visit visit) throws DataAccessException;
+	
+	public Collection<Vet> getVets() throws DataAccessException;
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/service/ClinicServiceImpl.java b/src/main/java/org/springframework/samples/petclinic/service/ClinicServiceImpl.java
new file mode 100644
index 0000000..b4e51e7
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/service/ClinicServiceImpl.java
@@ -0,0 +1,71 @@
+package org.springframework.samples.petclinic.service;
+
+import java.util.Collection;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataAccessException;
+import org.springframework.samples.petclinic.Owner;
+import org.springframework.samples.petclinic.Pet;
+import org.springframework.samples.petclinic.PetType;
+import org.springframework.samples.petclinic.Vet;
+import org.springframework.samples.petclinic.Visit;
+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;
+
+@Service
+public class ClinicServiceImpl implements ClinicService {
+	
+	@Autowired
+	private PetRepository petRepository;
+	
+	@Autowired
+	private VetRepository vetRepository;
+	
+	@Autowired
+	private OwnerRepository ownerRepository;
+	
+	@Autowired
+	private VisitRepository visitRepository;
+
+	public Collection<PetType> getPetTypes() throws DataAccessException {
+		return petRepository.getPetTypes();
+	}
+
+	public Owner findOwnerById(int id) throws DataAccessException {
+		return ownerRepository.findById(id);
+	}
+
+	public void storeVisit(Visit visit) throws DataAccessException {
+		visitRepository.storeVisit(visit);
+	}
+
+	public Pet findPetById(int id) throws DataAccessException {
+		return petRepository.findById(id);
+	}
+
+	public void storePet(Pet pet) throws DataAccessException {
+		petRepository.storePet(pet);
+	}
+
+	public void deletePet(int id) throws DataAccessException {
+		petRepository.deletePet(id);
+	}
+
+	public Collection<Vet> getVets() throws DataAccessException {
+		return vetRepository.getVets();
+	}
+	
+	
+	
+	
+	
+	
+	
+	
+	
+	
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/web/ClinicBindingInitializer.java b/src/main/java/org/springframework/samples/petclinic/web/ClinicBindingInitializer.java
index 2d2a8bd..4421ce0 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/ClinicBindingInitializer.java
+++ b/src/main/java/org/springframework/samples/petclinic/web/ClinicBindingInitializer.java
@@ -6,8 +6,8 @@ import java.util.Date;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.propertyeditors.CustomDateEditor;
 import org.springframework.beans.propertyeditors.StringTrimmerEditor;
-import org.springframework.samples.petclinic.Clinic;
 import org.springframework.samples.petclinic.PetType;
+import org.springframework.samples.petclinic.service.ClinicService;
 import org.springframework.web.bind.WebDataBinder;
 import org.springframework.web.bind.support.WebBindingInitializer;
 import org.springframework.web.context.request.WebRequest;
@@ -24,14 +24,14 @@ import org.springframework.web.context.request.WebRequest;
 public class ClinicBindingInitializer implements WebBindingInitializer {
 
 	@Autowired
-	private Clinic clinic;
+	private ClinicService clinicService;
 
 	public void initBinder(WebDataBinder binder, WebRequest request) {
 		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
 		dateFormat.setLenient(false);
 		binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
 		binder.registerCustomEditor(String.class, new StringTrimmerEditor(false));
-		binder.registerCustomEditor(PetType.class, new PetTypeEditor(this.clinic));
+		binder.registerCustomEditor(PetType.class, new PetTypeEditor(this.clinicService));
 	}
 
 }
diff --git a/src/main/java/org/springframework/samples/petclinic/web/ClinicController.java b/src/main/java/org/springframework/samples/petclinic/web/ClinicController.java
deleted file mode 100644
index 8d5ea2d..0000000
--- a/src/main/java/org/springframework/samples/petclinic/web/ClinicController.java
+++ /dev/null
@@ -1,99 +0,0 @@
-
-package org.springframework.samples.petclinic.web;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.propertyeditors.CustomDateEditor;
-import org.springframework.beans.propertyeditors.StringTrimmerEditor;
-import org.springframework.samples.petclinic.Clinic;
-import org.springframework.samples.petclinic.PetType;
-import org.springframework.samples.petclinic.Vets;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.ui.ModelMap;
-import org.springframework.web.bind.WebDataBinder;
-import org.springframework.web.bind.annotation.InitBinder;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.servlet.ModelAndView;
-
-/**
- * Annotation-driven <em>MultiActionController</em> that handles all non-form
- * URL's.
- *
- * @author Juergen Hoeller
- * @author Mark Fisher
- * @author Ken Krebs
- * @author Arjen Poutsma
- */
-@Controller
-public class ClinicController {
-
-	private final Clinic clinic;
-
-
-	@Autowired
-	public ClinicController(Clinic clinic) {
-		this.clinic = clinic;
-	}
-
-	/**
-	 * Custom handler for the welcome view.
-	 * <p>
-	 * Note that this handler relies on the RequestToViewNameTranslator to
-	 * determine the logical view name based on the request URL: "/welcome.do"
-	 * -&gt; "welcome".
-	 */
-	@RequestMapping("/")
-	public String welcomeHandler() {
-		return "welcome";
-	}
-
-	/**
-	 * Custom handler for displaying vets.
-	 *
-	 * <p>Note that this handler returns a plain {@link ModelMap} object instead of
-	 * a ModelAndView, thus leveraging convention-based model attribute names.
-	 * It relies on the RequestToViewNameTranslator to determine the logical
-	 * view name based on the request URL: "/vets.do" -&gt; "vets".
-	 *
-	 * @return a ModelMap with the model attributes for the view
-	 */
-	@RequestMapping("/vets")
-	public String showVetList(Model model) {
-		Vets vets = new Vets();
-		vets.getVetList().addAll(this.clinic.getVets());
-		model.addAttribute("vets", vets);
-		return "vetsList";
-	}
-
-	/**
-	 * Custom handler for displaying an owner.
-	 *
-	 * @param ownerId the ID of the owner to display
-	 * @return a ModelMap with the model attributes for the view
-	 */
-	@RequestMapping("/owners/{ownerId}")
-	public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) {
-		ModelAndView mav = new ModelAndView("owners/ownerDetails");
-		mav.addObject(this.clinic.findOwner(ownerId));
-		return mav;
-	}
-
-	/**
-	 * Custom handler for displaying an list of visits.
-	 *
-	 * @param petId the ID of the pet whose visits to display
-	 * @return a ModelMap with the model attributes for the view
-	 */
-	@RequestMapping(value="/owners/*/pets/{petId}/visits", method=RequestMethod.GET)
-	public ModelAndView visitsHandler(@PathVariable int petId) {
-		ModelAndView mav = new ModelAndView("visits");
-		mav.addObject("visits", this.clinic.findPet(petId).getVisits());
-		return mav;
-	}
-
-}
diff --git a/src/main/java/org/springframework/samples/petclinic/web/OwnerController.java b/src/main/java/org/springframework/samples/petclinic/web/OwnerController.java
index 7b9fb49..a7f760a 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/OwnerController.java
+++ b/src/main/java/org/springframework/samples/petclinic/web/OwnerController.java
@@ -6,8 +6,8 @@ import java.util.Collection;
 import javax.validation.Valid;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.samples.petclinic.Clinic;
 import org.springframework.samples.petclinic.Owner;
+import org.springframework.samples.petclinic.repository.OwnerRepository;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.validation.BindingResult;
@@ -18,6 +18,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.SessionAttributes;
 import org.springframework.web.bind.support.SessionStatus;
+import org.springframework.web.servlet.ModelAndView;
 
 /**
  * JavaBean form controller that is used to handle <code>Owner</code>s .
@@ -31,12 +32,12 @@ import org.springframework.web.bind.support.SessionStatus;
 @SessionAttributes(types = Owner.class)
 public class OwnerController {
 
-	private final Clinic clinic;
+	private final OwnerRepository ownerRepository;
 
 
 	@Autowired
-	public OwnerController(Clinic clinic) {
-		this.clinic = clinic;
+	public OwnerController(OwnerRepository ownerRepository) {
+		this.ownerRepository = ownerRepository;
 	}
 
 	@InitBinder
@@ -57,7 +58,7 @@ public class OwnerController {
 			return "owners/createOrUpdateOwnerForm";
 		}
 		else {
-			this.clinic.storeOwner(owner);
+			this.ownerRepository.save(owner);
 			status.setComplete();
 			return "redirect:/owners/" + owner.getId();
 		}
@@ -78,7 +79,7 @@ public class OwnerController {
 		}
 
 		// find owners by last name
-		Collection<Owner> results = this.clinic.findOwners(owner.getLastName());
+		Collection<Owner> results = this.ownerRepository.findByLastName(owner.getLastName());
 		if (results.size() < 1) {
 			// no owners found
 			result.rejectValue("lastName", "notFound", "not found");
@@ -98,7 +99,7 @@ public class OwnerController {
 	
 	@RequestMapping(value="/owners/{ownerId}/edit", method = RequestMethod.GET)
 	public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) {
-		Owner owner = this.clinic.findOwner(ownerId);
+		Owner owner = this.ownerRepository.findById(ownerId);
 		model.addAttribute(owner);
 		return "owners/createOrUpdateOwnerForm";
 	}
@@ -109,10 +110,23 @@ public class OwnerController {
 			return "owners/createOrUpdateOwnerForm";
 		}
 		else {
-			this.clinic.storeOwner(owner);
+			this.ownerRepository.save(owner);
 			status.setComplete();
 			return "redirect:/owners/" + owner.getId();
 		}
 	}
+	
+	/**
+	 * Custom handler for displaying an owner.
+	 *
+	 * @param ownerId the ID of the owner to display
+	 * @return a ModelMap with the model attributes for the view
+	 */
+	@RequestMapping("/owners/{ownerId}")
+	public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) {
+		ModelAndView mav = new ModelAndView("owners/ownerDetails");
+		mav.addObject(this.ownerRepository.findById(ownerId));
+		return mav;
+	}
 
 }
diff --git a/src/main/java/org/springframework/samples/petclinic/web/PetController.java b/src/main/java/org/springframework/samples/petclinic/web/PetController.java
index 55e4e93..b440a79 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/PetController.java
+++ b/src/main/java/org/springframework/samples/petclinic/web/PetController.java
@@ -4,10 +4,10 @@ package org.springframework.samples.petclinic.web;
 import java.util.Collection;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.samples.petclinic.Clinic;
 import org.springframework.samples.petclinic.Owner;
 import org.springframework.samples.petclinic.Pet;
 import org.springframework.samples.petclinic.PetType;
+import org.springframework.samples.petclinic.service.ClinicService;
 import org.springframework.samples.petclinic.validation.PetValidator;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
@@ -33,17 +33,17 @@ import org.springframework.web.bind.support.SessionStatus;
 @SessionAttributes("pet")
 public class PetController {
 
-	private final Clinic clinic;
-
+	private final ClinicService clinicService;
 
+ 
 	@Autowired
-	public PetController(Clinic clinic) {
-		this.clinic = clinic;
+	public PetController(ClinicService clinicService) {
+		this.clinicService = clinicService;
 	}
 
 	@ModelAttribute("types")
 	public Collection<PetType> populatePetTypes() {
-		return this.clinic.getPetTypes();
+		return this.clinicService.getPetTypes();
 	}
 
 	@InitBinder
@@ -53,7 +53,7 @@ public class PetController {
 
 	@RequestMapping(value="/owners/{ownerId}/pets/new",  method = RequestMethod.GET)
 	public String initCreationForm(@PathVariable("ownerId") int ownerId, Model model) {
-		Owner owner = this.clinic.findOwner(ownerId);
+		Owner owner = this.clinicService.findOwnerById(ownerId);
 		Pet pet = new Pet();
 		owner.addPet(pet);
 		model.addAttribute("pet", pet);
@@ -67,7 +67,7 @@ public class PetController {
 			return "pets/createOrUpdatePetForm";
 		}
 		else {
-			this.clinic.storePet(pet);
+			this.clinicService.storePet(pet);
 			status.setComplete();
 			return "redirect:/owners/" + pet.getOwner().getId();
 		}
@@ -75,7 +75,7 @@ public class PetController {
 	
 	@RequestMapping(value="/owners/*/pets/{petId}/edit", method = RequestMethod.GET)
 	public String initUpdateForm(@PathVariable("petId") int petId, Model model) {
-		Pet pet = this.clinic.findPet(petId);
+		Pet pet = this.clinicService.findPetById(petId);
 		model.addAttribute("pet", pet);
 		return "pets/createOrUpdatePetForm";
 	}
@@ -88,7 +88,7 @@ public class PetController {
 			return "pets/createOrUpdatePetForm";
 		}
 		else {
-			this.clinic.storePet(pet);
+			this.clinicService.storePet(pet);
 			status.setComplete();
 			return "redirect:/owners/" + pet.getOwner().getId();
 		}
@@ -96,8 +96,8 @@ public class PetController {
 
 	@RequestMapping(value="/owners/*/pets/{petId}/edit", method = RequestMethod.DELETE)
 	public String deletePet(@PathVariable("petId") int petId) {
-		Pet pet = this.clinic.findPet(petId);
-		this.clinic.deletePet(petId);
+		Pet pet = this.clinicService.findPetById(petId);
+		this.clinicService.deletePet(petId);
 		return "redirect:/owners/" + pet.getOwner().getId();
 	}
 
diff --git a/src/main/java/org/springframework/samples/petclinic/web/PetTypeEditor.java b/src/main/java/org/springframework/samples/petclinic/web/PetTypeEditor.java
index 812b648..1be37c9 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/PetTypeEditor.java
+++ b/src/main/java/org/springframework/samples/petclinic/web/PetTypeEditor.java
@@ -2,8 +2,8 @@ package org.springframework.samples.petclinic.web;
 
 import java.beans.PropertyEditorSupport;
 
-import org.springframework.samples.petclinic.Clinic;
 import org.springframework.samples.petclinic.PetType;
+import org.springframework.samples.petclinic.service.ClinicService;
 
 /**
  * @author Mark Fisher
@@ -11,16 +11,16 @@ import org.springframework.samples.petclinic.PetType;
  */
 public class PetTypeEditor extends PropertyEditorSupport {
 
-	private final Clinic clinic;
+	private final ClinicService clinicService;
 
 
-	public PetTypeEditor(Clinic clinic) {
-		this.clinic = clinic;
+	public PetTypeEditor(ClinicService clinicService) {
+		this.clinicService = clinicService;
 	}
 
 	@Override
 	public void setAsText(String text) throws IllegalArgumentException {
-		for (PetType type : this.clinic.getPetTypes()) {
+		for (PetType type : this.clinicService.getPetTypes()) {
 			if (type.getName().equals(text)) {
 				setValue(type);
 			}
diff --git a/src/main/java/org/springframework/samples/petclinic/web/VetController.java b/src/main/java/org/springframework/samples/petclinic/web/VetController.java
new file mode 100644
index 0000000..5bcdfa2
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/web/VetController.java
@@ -0,0 +1,54 @@
+
+package org.springframework.samples.petclinic.web;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.samples.petclinic.Vets;
+import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * Annotation-driven <em>MultiActionController</em> that handles all non-form
+ * URL's.
+ *
+ * @author Juergen Hoeller
+ * @author Mark Fisher
+ * @author Ken Krebs
+ * @author Arjen Poutsma
+ */
+@Controller
+public class VetController {
+
+	private final ClinicService clinicService;
+
+
+	@Autowired
+	public VetController(ClinicService clinicService) {
+		this.clinicService = clinicService;
+	}
+
+	/**
+	 * Custom handler for displaying vets.
+	 *
+	 * <p>Note that this handler returns a plain {@link ModelMap} object instead of
+	 * a ModelAndView, thus leveraging convention-based model attribute names.
+	 * It relies on the RequestToViewNameTranslator to determine the logical
+	 * view name based on the request URL: "/vets.do" -&gt; "vets".
+	 *
+	 * @return a ModelMap with the model attributes for the view
+	 */
+	@RequestMapping("/vets")
+	public String showVetList(Model model) {
+		Vets vets = new Vets();
+		vets.getVetList().addAll(this.clinicService.getVets());
+		model.addAttribute("vets", vets);
+		return "vetsList";
+	}
+
+
+
+
+
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/web/VisitController.java b/src/main/java/org/springframework/samples/petclinic/web/VisitController.java
index 0f38743..f093c04 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/VisitController.java
+++ b/src/main/java/org/springframework/samples/petclinic/web/VisitController.java
@@ -4,9 +4,9 @@ package org.springframework.samples.petclinic.web;
 import javax.validation.Valid;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.samples.petclinic.Clinic;
 import org.springframework.samples.petclinic.Pet;
 import org.springframework.samples.petclinic.Visit;
+import org.springframework.samples.petclinic.service.ClinicService;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.validation.BindingResult;
@@ -17,6 +17,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.SessionAttributes;
 import org.springframework.web.bind.support.SessionStatus;
+import org.springframework.web.servlet.ModelAndView;
 
 /**
  * JavaBean form controller that is used to add a new <code>Visit</code> to the
@@ -30,12 +31,12 @@ import org.springframework.web.bind.support.SessionStatus;
 @SessionAttributes("visit")
 public class VisitController {
 
-	private final Clinic clinic;
+	private final ClinicService clinicService;
 
 
 	@Autowired
-	public VisitController(Clinic clinic) {
-		this.clinic = clinic;
+	public VisitController(ClinicService clinicService) {
+		this.clinicService = clinicService;
 	}
 
 	@InitBinder
@@ -44,8 +45,8 @@ public class VisitController {
 	}
 
 	@RequestMapping(value="/owners/*/pets/{petId}/visits/new", method = RequestMethod.GET)
-	public String setupForm(@PathVariable("petId") int petId, Model model) {
-		Pet pet = this.clinic.findPet(petId);
+	public String initNewVisitForm(@PathVariable("petId") int petId, Model model) {
+		Pet pet = this.clinicService.findPetById(petId);
 		Visit visit = new Visit();
 		pet.addVisit(visit);
 		model.addAttribute("visit", visit);
@@ -53,15 +54,28 @@ public class VisitController {
 	}
 
 	@RequestMapping(value="/owners/*/pets/{petId}/visits/new", method = RequestMethod.POST)
-	public String processSubmit(@Valid Visit visit, BindingResult result, SessionStatus status) {
+	public String processNewVisitForm(@Valid Visit visit, BindingResult result, SessionStatus status) {
 		if (result.hasErrors()) {
 			return "pets/createOrUpdateVisitForm";
 		}
 		else {
-			this.clinic.storeVisit(visit);
+			this.clinicService.storeVisit(visit);
 			status.setComplete();
 			return "redirect:/owners/" + visit.getPet().getOwner().getId();
 		}
 	}
+	
+	/**
+	 * Custom handler for displaying an list of visits.
+	 *
+	 * @param petId the ID of the pet whose visits to display
+	 * @return a ModelMap with the model attributes for the view
+	 */
+	@RequestMapping(value="/owners/*/pets/{petId}/visits", method=RequestMethod.GET)
+	public ModelAndView showVisits(@PathVariable int petId) {
+		ModelAndView mav = new ModelAndView("visits");
+		mav.addObject("visits", this.clinicService.findPetById(petId).getVisits());
+		return mav;
+	}
 
 }
diff --git a/src/main/java/org/springframework/samples/petclinic/web/VisitsAtomView.java b/src/main/java/org/springframework/samples/petclinic/web/VisitsAtomView.java
index e9da832..f5f69e0 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/VisitsAtomView.java
+++ b/src/main/java/org/springframework/samples/petclinic/web/VisitsAtomView.java
@@ -41,7 +41,7 @@ public class VisitsAtomView extends AbstractAtomFeedView {
 	@Override
 	protected void buildFeedMetadata(Map<String, Object> model, Feed feed, HttpServletRequest request) {
 		feed.setId("tag:springsource.com");
-		feed.setTitle("Pet Clinic Visits");
+		feed.setTitle("Pet ClinicService Visits");
 		@SuppressWarnings("unchecked")
 		List<Visit> visits = (List<Visit>) model.get("visits");
 		for (Visit visit : visits) {
diff --git a/src/main/resources/spring/applicationContext-dao.xml b/src/main/resources/spring/applicationContext-dao.xml
index 1ce9718..69f23d9 100644
--- a/src/main/resources/spring/applicationContext-dao.xml
+++ b/src/main/resources/spring/applicationContext-dao.xml
@@ -96,10 +96,16 @@
 			<!-- Transaction manager for a single JDBC DataSource (alternative to JTA) -->
 			<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
 				p:dataSource-ref="dataSource"/>
-		
-	
-		<!-- PetClinic's central data access object using Spring's SimpleJdbcTemplate -->
-		<bean id="clinic" class="org.springframework.samples.petclinic.jdbc.JdbcClinicImpl"/>
+
+			<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
+				<constructor-arg ref="dataSource" />			
+			</bean>
+			
+			<bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
+				<constructor-arg ref="dataSource" />			
+			</bean>
+			
+			<context:component-scan base-package="org.springframework.samples.petclinic.repository.jdbc"/>
 	
 	</beans>
 	
@@ -109,12 +115,12 @@
 			EntityManager will be auto-injected due to @PersistenceContext.
 			PersistenceExceptions will be auto-translated due to @Repository.
 		-->
-		<bean id="clinic" class="org.springframework.samples.petclinic.jpa.JpaClinicImpl"/>
+		<context:component-scan base-package="org.springframework.samples.petclinic.repository.jpa"/>
 	
 	</beans>
 	
 	<beans profile="spring-data-jpa">
-		<jpa:repositories base-package="org.springframework.samples.petclinic.jpa"/>
+		<jpa:repositories base-package="org.springframework.samples.petclinic.repository.jpa"/>
 	
 	</beans>
 </beans>
\ No newline at end of file
diff --git a/src/main/webapp/WEB-INF/petclinic-servlet.xml b/src/main/webapp/WEB-INF/petclinic-servlet.xml
index d203e4a..c619a4f 100644
--- a/src/main/webapp/WEB-INF/petclinic-servlet.xml
+++ b/src/main/webapp/WEB-INF/petclinic-servlet.xml
@@ -13,7 +13,7 @@
 	<!--
 		- The controllers are autodetected POJOs labeled with the @Controller annotation.
 	-->
-	<context:component-scan base-package="org.springframework.samples.petclinic.web"/>
+	<context:component-scan base-package="org.springframework.samples.petclinic.web, org.springframework.samples.petclinic.service"/>
 	
 	
 	 <mvc:annotation-driven  />
@@ -25,6 +25,8 @@
 	<!-- uses WebJars so Javascript and CSS libs can be declared as Maven dependencies (we're using it for Bootstrap) -->
 	<mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/"/>
 	
+	<mvc:view-controller path="/" view-name="welcome"/>
+	
 	
 <!--
 		- This view resolver delegates to the InternalResourceViewResolver and BeanNameViewResolver,
diff --git a/src/test/java/org/springframework/samples/petclinic/AbstractOwnerRepositoryTests.java b/src/test/java/org/springframework/samples/petclinic/AbstractOwnerRepositoryTests.java
new file mode 100644
index 0000000..9a516fc
--- /dev/null
+++ b/src/test/java/org/springframework/samples/petclinic/AbstractOwnerRepositoryTests.java
@@ -0,0 +1,147 @@
+package org.springframework.samples.petclinic;
+
+import java.util.Collection;
+import java.util.Date;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.samples.petclinic.repository.OwnerRepository;
+import org.springframework.samples.petclinic.util.EntityUtils;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * <p>
+ * Base class for {@link OwnerRepository} integration tests.
+ * </p>
+ * <p>
+ * &quot;AbstractClinicTests-context.xml&quot; declares a common
+ * {@link javax.sql.DataSource DataSource}. Subclasses should specify
+ * additional context locations which declare a
+ * {@link org.springframework.transaction.PlatformTransactionManager PlatformTransactionManager}
+ * and a concrete implementation of {@link OwnerRepository}.
+ * </p>
+ * <p>
+ * This class extends {@link AbstractTransactionalJUnit4SpringContextTests},
+ * one of the valuable testing support classes provided by the
+ * <em>Spring TestContext Framework</em> found in the
+ * <code>org.springframework.test.context</code> package. The
+ * annotation-driven configuration used here represents best practice for
+ * integration tests with Spring. Note, however, that
+ * AbstractTransactionalJUnit4SpringContextTests serves only as a convenience
+ * for extension. For example, if you do not wish for your test classes to be
+ * tied to a Spring-specific class hierarchy, you may configure your tests with
+ * annotations such as {@link ContextConfiguration @ContextConfiguration},
+ * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners},
+ * {@link org.springframework.transaction.annotation.Transactional @Transactional},
+ * etc.
+ * </p>
+ * <p>
+ * AbstractClinicTests and its subclasses benefit from the following services
+ * provided by the Spring TestContext Framework:
+ * </p>
+ * <ul>
+ * <li><strong>Spring IoC container caching</strong> which spares us
+ * unnecessary set up time between test execution.</li>
+ * <li><strong>Dependency Injection</strong> of test fixture instances,
+ * meaning that we don't need to perform application context lookups. See the
+ * use of {@link Autowired @Autowired} on the <code>ownerRepository</code> instance
+ * variable, which uses autowiring <em>by type</em>. As an alternative, we
+ * could annotate <code>ownerRepository</code> with
+ * {@link javax.annotation.Resource @Resource} to achieve dependency injection
+ * <em>by name</em>.
+ * <em>(see: {@link ContextConfiguration @ContextConfiguration},
+ * {@link org.springframework.test.context.support.DependencyInjectionTestExecutionListener DependencyInjectionTestExecutionListener})</em></li>
+ * <li><strong>Transaction management</strong>, meaning each test method is
+ * executed in its own transaction, which is automatically rolled back by
+ * default. Thus, even if tests insert or otherwise change database state, there
+ * is no need for a teardown or cleanup script.
+ * <em>(see: {@link org.springframework.test.context.transaction.TransactionConfiguration @TransactionConfiguration},
+ * {@link org.springframework.transaction.annotation.Transactional @Transactional},
+ * {@link org.springframework.test.context.transaction.TransactionalTestExecutionListener TransactionalTestExecutionListener})</em></li>
+ * <li><strong>Useful inherited protected fields</strong>, such as a
+ * {@link org.springframework.jdbc.core.simple.SimpleJdbcTemplate SimpleJdbcTemplate}
+ * that can be used to verify database state after test operations or to verify
+ * the results of queries performed by application code. An
+ * {@link org.springframework.context.ApplicationContext ApplicationContext} is
+ * also inherited and can be used for explicit bean lookup if necessary.
+ * <em>(see: {@link org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests AbstractJUnit4SpringContextTests},
+ * {@link AbstractTransactionalJUnit4SpringContextTests})</em></li>
+ * </ul>
+ * <p>
+ * The Spring TestContext Framework and related unit and integration testing
+ * support classes are shipped in <code>spring-test.jar</code>.
+ * </p>
+ *
+ * @author Ken Krebs
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Sam Brannen
+ */
+public abstract class AbstractOwnerRepositoryTests {
+
+	@Autowired
+	protected OwnerRepository ownerRepository;
+
+
+
+
+	@Test
+	public void findOwners() {
+		Collection<Owner> owners = this.ownerRepository.findByLastName("Davis");
+		assertEquals(2, owners.size());
+		owners = this.ownerRepository.findByLastName("Daviss");
+		assertEquals(0, owners.size());
+	}
+
+	@Test @Transactional
+	public void findOwner() {
+		Owner o1 = this.ownerRepository.findById(1);
+		assertTrue(o1.getLastName().startsWith("Franklin"));
+		Owner o10 = this.ownerRepository.findById(10);
+		assertEquals("Carlos", o10.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.
+		// 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
+	public void insertOwner() {
+		Collection<Owner> owners = this.ownerRepository.findByLastName("Schultz");
+		int found = owners.size();
+		Owner owner = new Owner();
+		owner.setFirstName("Sam");
+		owner.setLastName("Schultz");
+		owner.setAddress("4, Evans Street");
+		owner.setCity("Wollongong");
+		owner.setTelephone("4444444444");
+		this.ownerRepository.save(owner);
+		owners = this.ownerRepository.findByLastName("Schultz");
+		assertEquals("Verifying number of owners after inserting a new one.", found + 1, owners.size());
+	}
+
+	@Test
+	public void updateOwner() throws Exception {
+		Owner o1 = this.ownerRepository.findById(1);
+		String old = o1.getLastName();
+		o1.setLastName(old + "X");
+		this.ownerRepository.save(o1);
+		o1 = this.ownerRepository.findById(1);
+		assertEquals(old + "X", o1.getLastName());
+	}
+
+
+
+}
diff --git a/src/test/java/org/springframework/samples/petclinic/AbstractClinicTests.java b/src/test/java/org/springframework/samples/petclinic/AbstractPetRepositoryTests.java
similarity index 60%
rename from src/test/java/org/springframework/samples/petclinic/AbstractClinicTests.java
rename to src/test/java/org/springframework/samples/petclinic/AbstractPetRepositoryTests.java
index a9246d4..8db0a5f 100644
--- a/src/test/java/org/springframework/samples/petclinic/AbstractClinicTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/AbstractPetRepositoryTests.java
@@ -8,6 +8,9 @@ import static org.junit.Assert.assertTrue;
 import org.junit.Test;
 
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.samples.petclinic.repository.OwnerRepository;
+import org.springframework.samples.petclinic.repository.PetRepository;
+import org.springframework.samples.petclinic.service.ClinicService;
 import org.springframework.samples.petclinic.util.EntityUtils;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
@@ -15,14 +18,14 @@ import org.springframework.transaction.annotation.Transactional;
 
 /**
  * <p>
- * Base class for {@link Clinic} integration tests.
+ * Base class for {@link ClinicService} integration tests.
  * </p>
  * <p>
  * &quot;AbstractClinicTests-context.xml&quot; declares a common
  * {@link javax.sql.DataSource DataSource}. Subclasses should specify
  * additional context locations which declare a
  * {@link org.springframework.transaction.PlatformTransactionManager PlatformTransactionManager}
- * and a concrete implementation of {@link Clinic}.
+ * and a concrete implementation of {@link ClinicService}.
  * </p>
  * <p>
  * This class extends {@link AbstractTransactionalJUnit4SpringContextTests},
@@ -48,9 +51,9 @@ import org.springframework.transaction.annotation.Transactional;
  * unnecessary set up time between test execution.</li>
  * <li><strong>Dependency Injection</strong> of test fixture instances,
  * meaning that we don't need to perform application context lookups. See the
- * use of {@link Autowired @Autowired} on the <code>clinic</code> instance
+ * use of {@link Autowired @Autowired} on the <code>petRepository</code> instance
  * variable, which uses autowiring <em>by type</em>. As an alternative, we
- * could annotate <code>clinic</code> with
+ * could annotate <code>petRepository</code> with
  * {@link javax.annotation.Resource @Resource} to achieve dependency injection
  * <em>by name</em>.
  * <em>(see: {@link ContextConfiguration @ContextConfiguration},
@@ -81,30 +84,18 @@ import org.springframework.transaction.annotation.Transactional;
  * @author Juergen Hoeller
  * @author Sam Brannen
  */
-public abstract class AbstractClinicTests {
+public abstract class AbstractPetRepositoryTests {
 
 	@Autowired
-	protected Clinic clinic;
-
+	protected PetRepository petRepository;
+	
+	@Autowired
+	protected OwnerRepository ownerRepository;
 
-	@Test @Transactional
-	public void getVets() {
-		Collection<Vet> vets = this.clinic.getVets();
-		
-		Vet v1 = EntityUtils.getById(vets, Vet.class, 2);
-		assertEquals("Leary", v1.getLastName());
-		assertEquals(1, v1.getNrOfSpecialties());
-		assertEquals("radiology", (v1.getSpecialties().get(0)).getName());
-		Vet v2 = EntityUtils.getById(vets, Vet.class, 3);
-		assertEquals("Douglas", v2.getLastName());
-		assertEquals(2, v2.getNrOfSpecialties());
-		assertEquals("dentistry", (v2.getSpecialties().get(0)).getName());
-		assertEquals("surgery", (v2.getSpecialties().get(1)).getName());
-	}
 
 	@Test
 	public void getPetTypes() {
-		Collection<PetType> petTypes = this.clinic.getPetTypes();
+		Collection<PetType> petTypes = this.petRepository.getPetTypes();
 		
 		PetType t1 = EntityUtils.getById(petTypes, PetType.class, 1);
 		assertEquals("cat", t1.getName());
@@ -112,63 +103,14 @@ public abstract class AbstractClinicTests {
 		assertEquals("snake", t4.getName());
 	}
 
-	@Test
-	public void findOwners() {
-		Collection<Owner> owners = this.clinic.findOwners("Davis");
-		assertEquals(2, owners.size());
-		owners = this.clinic.findOwners("Daviss");
-		assertEquals(0, owners.size());
-	}
-
-	@Test @Transactional
-	public void findOwner() {
-		Owner o1 = this.clinic.findOwner(1);
-		assertTrue(o1.getLastName().startsWith("Franklin"));
-		Owner o10 = this.clinic.findOwner(10);
-		assertEquals("Carlos", o10.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.
-		// 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
-	public void insertOwner() {
-		Collection<Owner> owners = this.clinic.findOwners("Schultz");
-		int found = owners.size();
-		Owner owner = new Owner();
-		owner.setLastName("Schultz");
-		this.clinic.storeOwner(owner);
-		// assertTrue(!owner.isNew()); -- NOT TRUE FOR TOPLINK (before commit)
-		owners = this.clinic.findOwners("Schultz");
-		assertEquals("Verifying number of owners after inserting a new one.", found + 1, owners.size());
-	}
-
-	@Test
-	public void updateOwner() throws Exception {
-		Owner o1 = this.clinic.findOwner(1);
-		String old = o1.getLastName();
-		o1.setLastName(old + "X");
-		this.clinic.storeOwner(o1);
-		o1 = this.clinic.findOwner(1);
-		assertEquals(old + "X", o1.getLastName());
-	}
-
 	@Test
 	public void findPet() {
-		Collection<PetType> types = this.clinic.getPetTypes();
-		Pet p7 = this.clinic.findPet(7);
+		Collection<PetType> types = this.petRepository.getPetTypes();
+		Pet p7 = this.petRepository.findById(7);
 		assertTrue(p7.getName().startsWith("Samantha"));
 		assertEquals(EntityUtils.getById(types, PetType.class, 1).getId(), p7.getType().getId());
 		assertEquals("Jean", p7.getOwner().getFirstName());
-		Pet p6 = this.clinic.findPet(6);
+		Pet p6 = this.petRepository.findById(6);
 		assertEquals("George", p6.getName());
 		assertEquals(EntityUtils.getById(types, PetType.class, 4).getId(), p6.getType().getId());
 		assertEquals("Peter", p6.getOwner().getFirstName());
@@ -176,46 +118,30 @@ public abstract class AbstractClinicTests {
 
 	@Test @Transactional
 	public void insertPet() {
-		Owner o6 = this.clinic.findOwner(6);
+		Owner o6 = this.ownerRepository.findById(6);
 		int found = o6.getPets().size();
 		Pet pet = new Pet();
 		pet.setName("bowser");
-		Collection<PetType> types = this.clinic.getPetTypes();
+		Collection<PetType> types = this.petRepository.getPetTypes();
 		pet.setType(EntityUtils.getById(types, PetType.class, 2));
 		pet.setBirthDate(new Date());
 		o6.addPet(pet);
 		assertEquals(found + 1, o6.getPets().size());
 		// both storePet and storeOwner are necessary to cover all ORM tools
-		this.clinic.storePet(pet);
-		this.clinic.storeOwner(o6);
-		// assertTrue(!pet.isNew()); -- NOT TRUE FOR TOPLINK (before commit)
-		o6 = this.clinic.findOwner(6);
+		this.petRepository.storePet(pet);
+		this.ownerRepository.save(o6);
+		o6 = this.ownerRepository.findById(6);
 		assertEquals(found + 1, o6.getPets().size());
 	}
 
 	@Test
 	public void updatePet() throws Exception {
-		Pet p7 = this.clinic.findPet(7);
+		Pet p7 = this.petRepository.findById(7);
 		String old = p7.getName();
 		p7.setName(old + "X");
-		this.clinic.storePet(p7);
-		p7 = this.clinic.findPet(7);
+		this.petRepository.storePet(p7);
+		p7 = this.petRepository.findById(7);
 		assertEquals(old + "X", p7.getName());
 	}
 
-	@Test  @Transactional
-	public void insertVisit() {
-		Pet p7 = this.clinic.findPet(7);
-		int found = p7.getVisits().size();
-		Visit visit = new Visit();
-		p7.addVisit(visit);
-		visit.setDescription("test");
-		// both storeVisit and storePet are necessary to cover all ORM tools
-		this.clinic.storeVisit(visit);
-		this.clinic.storePet(p7);
-		// assertTrue(!visit.isNew()); -- NOT TRUE FOR TOPLINK (before commit)
-		p7 = this.clinic.findPet(7);
-		assertEquals(found + 1, p7.getVisits().size());
-	}
-
 }
diff --git a/src/test/java/org/springframework/samples/petclinic/AbstractVetRepositoryTests.java b/src/test/java/org/springframework/samples/petclinic/AbstractVetRepositoryTests.java
new file mode 100644
index 0000000..8db1f77
--- /dev/null
+++ b/src/test/java/org/springframework/samples/petclinic/AbstractVetRepositoryTests.java
@@ -0,0 +1,107 @@
+package org.springframework.samples.petclinic;
+
+import java.util.Collection;
+import java.util.Date;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.samples.petclinic.repository.VetRepository;
+import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.samples.petclinic.util.EntityUtils;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * <p>
+ * Base class for {@link ClinicService} integration tests.
+ * </p>
+ * <p>
+ * &quot;AbstractClinicTests-context.xml&quot; declares a common
+ * {@link javax.sql.DataSource DataSource}. Subclasses should specify
+ * additional context locations which declare a
+ * {@link org.springframework.transaction.PlatformTransactionManager PlatformTransactionManager}
+ * and a concrete implementation of {@link ClinicService}.
+ * </p>
+ * <p>
+ * This class extends {@link AbstractTransactionalJUnit4SpringContextTests},
+ * one of the valuable testing support classes provided by the
+ * <em>Spring TestContext Framework</em> found in the
+ * <code>org.springframework.test.context</code> package. The
+ * annotation-driven configuration used here represents best practice for
+ * integration tests with Spring. Note, however, that
+ * AbstractTransactionalJUnit4SpringContextTests serves only as a convenience
+ * for extension. For example, if you do not wish for your test classes to be
+ * tied to a Spring-specific class hierarchy, you may configure your tests with
+ * annotations such as {@link ContextConfiguration @ContextConfiguration},
+ * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners},
+ * {@link org.springframework.transaction.annotation.Transactional @Transactional},
+ * etc.
+ * </p>
+ * <p>
+ * AbstractClinicTests and its subclasses benefit from the following services
+ * provided by the Spring TestContext Framework:
+ * </p>
+ * <ul>
+ * <li><strong>Spring IoC container caching</strong> which spares us
+ * unnecessary set up time between test execution.</li>
+ * <li><strong>Dependency Injection</strong> of test fixture instances,
+ * meaning that we don't need to perform application context lookups. See the
+ * use of {@link Autowired @Autowired} on the <code>petRepository</code> instance
+ * variable, which uses autowiring <em>by type</em>. As an alternative, we
+ * could annotate <code>petRepository</code> with
+ * {@link javax.annotation.Resource @Resource} to achieve dependency injection
+ * <em>by name</em>.
+ * <em>(see: {@link ContextConfiguration @ContextConfiguration},
+ * {@link org.springframework.test.context.support.DependencyInjectionTestExecutionListener DependencyInjectionTestExecutionListener})</em></li>
+ * <li><strong>Transaction management</strong>, meaning each test method is
+ * executed in its own transaction, which is automatically rolled back by
+ * default. Thus, even if tests insert or otherwise change database state, there
+ * is no need for a teardown or cleanup script.
+ * <em>(see: {@link org.springframework.test.context.transaction.TransactionConfiguration @TransactionConfiguration},
+ * {@link org.springframework.transaction.annotation.Transactional @Transactional},
+ * {@link org.springframework.test.context.transaction.TransactionalTestExecutionListener TransactionalTestExecutionListener})</em></li>
+ * <li><strong>Useful inherited protected fields</strong>, such as a
+ * {@link org.springframework.jdbc.core.simple.SimpleJdbcTemplate SimpleJdbcTemplate}
+ * that can be used to verify database state after test operations or to verify
+ * the results of queries performed by application code. An
+ * {@link org.springframework.context.ApplicationContext ApplicationContext} is
+ * also inherited and can be used for explicit bean lookup if necessary.
+ * <em>(see: {@link org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests AbstractJUnit4SpringContextTests},
+ * {@link AbstractTransactionalJUnit4SpringContextTests})</em></li>
+ * </ul>
+ * <p>
+ * The Spring TestContext Framework and related unit and integration testing
+ * support classes are shipped in <code>spring-test.jar</code>.
+ * </p>
+ *
+ * @author Ken Krebs
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Sam Brannen
+ */
+public abstract class AbstractVetRepositoryTests {
+
+	@Autowired
+	protected VetRepository vetRepository;
+
+
+	@Test @Transactional
+	public void getVets() {
+		Collection<Vet> vets = this.vetRepository.getVets();
+		
+		Vet v1 = EntityUtils.getById(vets, Vet.class, 2);
+		assertEquals("Leary", v1.getLastName());
+		assertEquals(1, v1.getNrOfSpecialties());
+		assertEquals("radiology", (v1.getSpecialties().get(0)).getName());
+		Vet v2 = EntityUtils.getById(vets, Vet.class, 3);
+		assertEquals("Douglas", v2.getLastName());
+		assertEquals(2, v2.getNrOfSpecialties());
+		assertEquals("dentistry", (v2.getSpecialties().get(0)).getName());
+		assertEquals("surgery", (v2.getSpecialties().get(1)).getName());
+	}
+
+}
diff --git a/src/test/java/org/springframework/samples/petclinic/AbstractVisitRepositoryTests.java b/src/test/java/org/springframework/samples/petclinic/AbstractVisitRepositoryTests.java
new file mode 100644
index 0000000..bdae7a8
--- /dev/null
+++ b/src/test/java/org/springframework/samples/petclinic/AbstractVisitRepositoryTests.java
@@ -0,0 +1,111 @@
+package org.springframework.samples.petclinic;
+
+import java.util.Collection;
+import java.util.Date;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.samples.petclinic.repository.PetRepository;
+import org.springframework.samples.petclinic.repository.VisitRepository;
+import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.samples.petclinic.util.EntityUtils;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * <p>
+ * Base class for {@link ClinicService} integration tests.
+ * </p>
+ * <p>
+ * &quot;AbstractClinicTests-context.xml&quot; declares a common
+ * {@link javax.sql.DataSource DataSource}. Subclasses should specify
+ * additional context locations which declare a
+ * {@link org.springframework.transaction.PlatformTransactionManager PlatformTransactionManager}
+ * and a concrete implementation of {@link ClinicService}.
+ * </p>
+ * <p>
+ * This class extends {@link AbstractTransactionalJUnit4SpringContextTests},
+ * one of the valuable testing support classes provided by the
+ * <em>Spring TestContext Framework</em> found in the
+ * <code>org.springframework.test.context</code> package. The
+ * annotation-driven configuration used here represents best practice for
+ * integration tests with Spring. Note, however, that
+ * AbstractTransactionalJUnit4SpringContextTests serves only as a convenience
+ * for extension. For example, if you do not wish for your test classes to be
+ * tied to a Spring-specific class hierarchy, you may configure your tests with
+ * annotations such as {@link ContextConfiguration @ContextConfiguration},
+ * {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners},
+ * {@link org.springframework.transaction.annotation.Transactional @Transactional},
+ * etc.
+ * </p>
+ * <p>
+ * AbstractClinicTests and its subclasses benefit from the following services
+ * provided by the Spring TestContext Framework:
+ * </p>
+ * <ul>
+ * <li><strong>Spring IoC container caching</strong> which spares us
+ * unnecessary set up time between test execution.</li>
+ * <li><strong>Dependency Injection</strong> of test fixture instances,
+ * meaning that we don't need to perform application context lookups. See the
+ * use of {@link Autowired @Autowired} on the <code>petRepository</code> instance
+ * variable, which uses autowiring <em>by type</em>. As an alternative, we
+ * could annotate <code>petRepository</code> with
+ * {@link javax.annotation.Resource @Resource} to achieve dependency injection
+ * <em>by name</em>.
+ * <em>(see: {@link ContextConfiguration @ContextConfiguration},
+ * {@link org.springframework.test.context.support.DependencyInjectionTestExecutionListener DependencyInjectionTestExecutionListener})</em></li>
+ * <li><strong>Transaction management</strong>, meaning each test method is
+ * executed in its own transaction, which is automatically rolled back by
+ * default. Thus, even if tests insert or otherwise change database state, there
+ * is no need for a teardown or cleanup script.
+ * <em>(see: {@link org.springframework.test.context.transaction.TransactionConfiguration @TransactionConfiguration},
+ * {@link org.springframework.transaction.annotation.Transactional @Transactional},
+ * {@link org.springframework.test.context.transaction.TransactionalTestExecutionListener TransactionalTestExecutionListener})</em></li>
+ * <li><strong>Useful inherited protected fields</strong>, such as a
+ * {@link org.springframework.jdbc.core.simple.SimpleJdbcTemplate SimpleJdbcTemplate}
+ * that can be used to verify database state after test operations or to verify
+ * the results of queries performed by application code. An
+ * {@link org.springframework.context.ApplicationContext ApplicationContext} is
+ * also inherited and can be used for explicit bean lookup if necessary.
+ * <em>(see: {@link org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests AbstractJUnit4SpringContextTests},
+ * {@link AbstractTransactionalJUnit4SpringContextTests})</em></li>
+ * </ul>
+ * <p>
+ * The Spring TestContext Framework and related unit and integration testing
+ * support classes are shipped in <code>spring-test.jar</code>.
+ * </p>
+ *
+ * @author Ken Krebs
+ * @author Rod Johnson
+ * @author Juergen Hoeller
+ * @author Sam Brannen
+ */
+public abstract class AbstractVisitRepositoryTests {
+
+	@Autowired
+	protected VisitRepository visitRepository;
+	
+	@Autowired
+	protected PetRepository petRepository;
+
+
+	@Test  @Transactional
+	public void insertVisit() {
+		Pet p7 = this.petRepository.findById(7);
+		int found = p7.getVisits().size();
+		Visit visit = new Visit();
+		p7.addVisit(visit);
+		visit.setDescription("test");
+		// both storeVisit and storePet are necessary to cover all ORM tools
+		this.visitRepository.storeVisit(visit);
+		this.petRepository.storePet(p7);
+		// assertTrue(!visit.isNew()); -- NOT TRUE FOR TOPLINK (before commit)
+		p7 = this.petRepository.findById(7);
+		assertEquals(found + 1, p7.getVisits().size());
+	}
+
+}
diff --git a/src/test/java/org/springframework/samples/petclinic/aspects/UsageLogAspectTests.java b/src/test/java/org/springframework/samples/petclinic/aspects/UsageLogAspectTests.java
index 2768909..929e1b9 100644
--- a/src/test/java/org/springframework/samples/petclinic/aspects/UsageLogAspectTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/aspects/UsageLogAspectTests.java
@@ -1,18 +1,17 @@
 package org.springframework.samples.petclinic.aspects;
 
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
 import java.util.List;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.samples.petclinic.Clinic;
-import org.springframework.samples.petclinic.aspects.UsageLogAspect;
-import org.springframework.samples.petclinic.jpa.JpaClinicImplTests;
+import org.springframework.samples.petclinic.repository.OwnerRepository;
 import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.assertFalse;
 
 /**
  * <p>
@@ -36,7 +35,7 @@ public class UsageLogAspectTests {
 	private UsageLogAspect usageLogAspect;
 	
 	@Autowired
-	private Clinic clinic;
+	private OwnerRepository ownerRepository;
 
 
 	@Test
@@ -45,8 +44,8 @@ public class UsageLogAspectTests {
 		String lastName2 = "Davis";
 		String lastName3 = "foo";
 
-		assertFalse(this.clinic.findOwners(lastName1).isEmpty());
-		assertFalse(this.clinic.findOwners(lastName2).isEmpty());
+		assertFalse(this.ownerRepository.findByLastName(lastName1).isEmpty());
+		assertFalse(this.ownerRepository.findByLastName(lastName2).isEmpty());
 
 		List<String> namesRequested = this.usageLogAspect.getNamesRequested();
 		assertTrue(namesRequested.contains(lastName1));
diff --git a/src/test/java/org/springframework/samples/petclinic/jdbc/JdbcOwnerRepositoryImplTests.java b/src/test/java/org/springframework/samples/petclinic/jdbc/JdbcOwnerRepositoryImplTests.java
new file mode 100644
index 0000000..4c2d352
--- /dev/null
+++ b/src/test/java/org/springframework/samples/petclinic/jdbc/JdbcOwnerRepositoryImplTests.java
@@ -0,0 +1,29 @@
+package org.springframework.samples.petclinic.jdbc;
+
+import org.junit.runner.RunWith;
+import org.springframework.samples.petclinic.AbstractOwnerRepositoryTests;
+import org.springframework.samples.petclinic.repository.jdbc.JdbcClinicImpl;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * <p>
+ * Integration tests for the {@link JdbcClinicImpl} implementation.
+ * </p>
+ * <p>
+ * </p>
+ *
+ * @author Thomas Risberg
+ * @author Michael Isvy 
+ */
+@ContextConfiguration(locations={"classpath:spring/applicationContext-dao.xml"})
+@RunWith(SpringJUnit4ClassRunner.class)
+@DirtiesContext
+@ActiveProfiles("jdbc")
+public class JdbcOwnerRepositoryImplTests extends AbstractOwnerRepositoryTests {
+	
+	
+
+}
diff --git a/src/test/java/org/springframework/samples/petclinic/jdbc/JdbcClinicImplTests.java b/src/test/java/org/springframework/samples/petclinic/jdbc/JdbcPetRepositoryImplTests.java
similarity index 74%
rename from src/test/java/org/springframework/samples/petclinic/jdbc/JdbcClinicImplTests.java
rename to src/test/java/org/springframework/samples/petclinic/jdbc/JdbcPetRepositoryImplTests.java
index bba9193..d62454a 100644
--- a/src/test/java/org/springframework/samples/petclinic/jdbc/JdbcClinicImplTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/jdbc/JdbcPetRepositoryImplTests.java
@@ -1,7 +1,8 @@
 package org.springframework.samples.petclinic.jdbc;
 
 import org.junit.runner.RunWith;
-import org.springframework.samples.petclinic.AbstractClinicTests;
+import org.springframework.samples.petclinic.AbstractPetRepositoryTests;
+import org.springframework.samples.petclinic.repository.jdbc.JdbcClinicImpl;
 import org.springframework.test.annotation.DirtiesContext;
 import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.ContextConfiguration;
@@ -21,7 +22,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 @RunWith(SpringJUnit4ClassRunner.class)
 @DirtiesContext
 @ActiveProfiles("jdbc")
-public class JdbcClinicImplTests extends AbstractClinicTests {
+public class JdbcPetRepositoryImplTests extends AbstractPetRepositoryTests {
 	
 	
 
diff --git a/src/test/java/org/springframework/samples/petclinic/jdbc/JdbcVetRepositoryImplTests.java b/src/test/java/org/springframework/samples/petclinic/jdbc/JdbcVetRepositoryImplTests.java
new file mode 100644
index 0000000..4e05009
--- /dev/null
+++ b/src/test/java/org/springframework/samples/petclinic/jdbc/JdbcVetRepositoryImplTests.java
@@ -0,0 +1,29 @@
+package org.springframework.samples.petclinic.jdbc;
+
+import org.junit.runner.RunWith;
+import org.springframework.samples.petclinic.AbstractVetRepositoryTests;
+import org.springframework.samples.petclinic.repository.jdbc.JdbcClinicImpl;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * <p>
+ * Integration tests for the {@link JdbcClinicImpl} implementation.
+ * </p>
+ * <p>
+ * </p>
+ *
+ * @author Thomas Risberg
+ * @author Michael Isvy 
+ */
+@ContextConfiguration(locations={"classpath:spring/applicationContext-dao.xml"})
+@RunWith(SpringJUnit4ClassRunner.class)
+@DirtiesContext
+@ActiveProfiles("jdbc")
+public class JdbcVetRepositoryImplTests extends AbstractVetRepositoryTests {
+	
+	
+
+}
diff --git a/src/test/java/org/springframework/samples/petclinic/jdbc/JdbcVisitRepositoryImplTests.java b/src/test/java/org/springframework/samples/petclinic/jdbc/JdbcVisitRepositoryImplTests.java
new file mode 100644
index 0000000..7d272aa
--- /dev/null
+++ b/src/test/java/org/springframework/samples/petclinic/jdbc/JdbcVisitRepositoryImplTests.java
@@ -0,0 +1,29 @@
+package org.springframework.samples.petclinic.jdbc;
+
+import org.junit.runner.RunWith;
+import org.springframework.samples.petclinic.AbstractVisitRepositoryTests;
+import org.springframework.samples.petclinic.repository.jdbc.JdbcClinicImpl;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * <p>
+ * Integration tests for the {@link JdbcClinicImpl} implementation.
+ * </p>
+ * <p>
+ * </p>
+ *
+ * @author Thomas Risberg
+ * @author Michael Isvy 
+ */
+@ContextConfiguration(locations={"classpath:spring/applicationContext-dao.xml"})
+@RunWith(SpringJUnit4ClassRunner.class)
+@DirtiesContext
+@ActiveProfiles("jdbc")
+public class JdbcVisitRepositoryImplTests extends AbstractVisitRepositoryTests {
+	
+	
+
+}
diff --git a/src/test/java/org/springframework/samples/petclinic/jpa/JpaClinicImplTests.java b/src/test/java/org/springframework/samples/petclinic/jpa/JpaOwnerRepositoryImplTests.java
similarity index 57%
rename from src/test/java/org/springframework/samples/petclinic/jpa/JpaClinicImplTests.java
rename to src/test/java/org/springframework/samples/petclinic/jpa/JpaOwnerRepositoryImplTests.java
index aed4fcb..92eee5e 100644
--- a/src/test/java/org/springframework/samples/petclinic/jpa/JpaClinicImplTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/jpa/JpaOwnerRepositoryImplTests.java
@@ -1,16 +1,8 @@
 
 package org.springframework.samples.petclinic.jpa;
 
-import static junit.framework.Assert.fail;
-
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-
-import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.samples.petclinic.AbstractClinicTests;
-import org.springframework.samples.petclinic.Clinic;
+import org.springframework.samples.petclinic.AbstractOwnerRepositoryTests;
 import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -37,23 +29,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 @ContextConfiguration(locations={"classpath:spring/applicationContext-dao.xml"})
 @RunWith(SpringJUnit4ClassRunner.class)
 @ActiveProfiles({"jpa","plain-jpa"})
-public class JpaClinicImplTests extends AbstractClinicTests {
-	
-	@PersistenceContext
-	private EntityManager entityManager;
-
-	@Autowired
-	private Clinic clinic;
-
-
-	@Test
-	public void testBogusJpql() {
-		try {
-			this.entityManager.createQuery("SELECT RUBBISH FROM RUBBISH HEAP").executeUpdate();
-			fail("exception was expected because of incorrect SQL statement");
-		} catch (Exception e) {
-			// expected
-		}
-	}
+public class JpaOwnerRepositoryImplTests extends AbstractOwnerRepositoryTests {
 	
 }
\ No newline at end of file
diff --git a/src/test/java/org/springframework/samples/petclinic/jpa/JpaPetRepositoryImplTests.java b/src/test/java/org/springframework/samples/petclinic/jpa/JpaPetRepositoryImplTests.java
new file mode 100644
index 0000000..12e123b
--- /dev/null
+++ b/src/test/java/org/springframework/samples/petclinic/jpa/JpaPetRepositoryImplTests.java
@@ -0,0 +1,29 @@
+package org.springframework.samples.petclinic.jpa;
+
+import org.junit.runner.RunWith;
+import org.springframework.samples.petclinic.AbstractPetRepositoryTests;
+import org.springframework.samples.petclinic.repository.jdbc.JdbcClinicImpl;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * <p>
+ * Integration tests for the {@link JdbcClinicImpl} implementation.
+ * </p>
+ * <p>
+ * </p>
+ *
+ * @author Thomas Risberg
+ * @author Michael Isvy 
+ */
+@ContextConfiguration(locations={"classpath:spring/applicationContext-dao.xml"})
+@RunWith(SpringJUnit4ClassRunner.class)
+@DirtiesContext
+@ActiveProfiles({"jpa","plain-jpa"})
+public class JpaPetRepositoryImplTests extends AbstractPetRepositoryTests {
+	
+	
+
+}
diff --git a/src/test/java/org/springframework/samples/petclinic/jpa/JpaVetRepositoryImplTests.java b/src/test/java/org/springframework/samples/petclinic/jpa/JpaVetRepositoryImplTests.java
new file mode 100644
index 0000000..7a0e0eb
--- /dev/null
+++ b/src/test/java/org/springframework/samples/petclinic/jpa/JpaVetRepositoryImplTests.java
@@ -0,0 +1,29 @@
+package org.springframework.samples.petclinic.jpa;
+
+import org.junit.runner.RunWith;
+import org.springframework.samples.petclinic.AbstractVetRepositoryTests;
+import org.springframework.samples.petclinic.repository.jdbc.JdbcClinicImpl;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * <p>
+ * Integration tests for the {@link JdbcClinicImpl} implementation.
+ * </p>
+ * <p>
+ * </p>
+ *
+ * @author Thomas Risberg
+ * @author Michael Isvy 
+ */
+@ContextConfiguration(locations={"classpath:spring/applicationContext-dao.xml"})
+@RunWith(SpringJUnit4ClassRunner.class)
+@DirtiesContext
+@ActiveProfiles({"jpa","plain-jpa"})
+public class JpaVetRepositoryImplTests extends AbstractVetRepositoryTests {
+	
+	
+
+}
diff --git a/src/test/java/org/springframework/samples/petclinic/jpa/JpaVisitRepositoryImplTests.java b/src/test/java/org/springframework/samples/petclinic/jpa/JpaVisitRepositoryImplTests.java
new file mode 100644
index 0000000..5205307
--- /dev/null
+++ b/src/test/java/org/springframework/samples/petclinic/jpa/JpaVisitRepositoryImplTests.java
@@ -0,0 +1,29 @@
+package org.springframework.samples.petclinic.jpa;
+
+import org.junit.runner.RunWith;
+import org.springframework.samples.petclinic.AbstractVisitRepositoryTests;
+import org.springframework.samples.petclinic.repository.jdbc.JdbcClinicImpl;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * <p>
+ * Integration tests for the {@link JdbcClinicImpl} implementation.
+ * </p>
+ * <p>
+ * </p>
+ *
+ * @author Thomas Risberg
+ * @author Michael Isvy 
+ */
+@ContextConfiguration(locations={"classpath:spring/applicationContext-dao.xml"})
+@RunWith(SpringJUnit4ClassRunner.class)
+@DirtiesContext
+@ActiveProfiles({"jpa","plain-jpa"})
+public class JpaVisitRepositoryImplTests extends AbstractVisitRepositoryTests {
+	
+	
+
+}
diff --git a/src/test/java/org/springframework/samples/petclinic/jpa/SpringDataClinicTests.java b/src/test/java/org/springframework/samples/petclinic/jpa/SpringDataOwnerRepositoryTests.java
similarity index 75%
rename from src/test/java/org/springframework/samples/petclinic/jpa/SpringDataClinicTests.java
rename to src/test/java/org/springframework/samples/petclinic/jpa/SpringDataOwnerRepositoryTests.java
index a7e1768..67706e0 100644
--- a/src/test/java/org/springframework/samples/petclinic/jpa/SpringDataClinicTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/jpa/SpringDataOwnerRepositoryTests.java
@@ -2,7 +2,7 @@
 package org.springframework.samples.petclinic.jpa;
 
 import org.junit.runner.RunWith;
-import org.springframework.samples.petclinic.AbstractClinicTests;
+import org.springframework.samples.petclinic.AbstractOwnerRepositoryTests;
 import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -14,6 +14,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 @ContextConfiguration(locations={"classpath:spring/applicationContext-dao.xml"})
 @RunWith(SpringJUnit4ClassRunner.class)
 @ActiveProfiles({"jpa","spring-data-jpa"})
-public class SpringDataClinicTests extends AbstractClinicTests {
+public class SpringDataOwnerRepositoryTests extends AbstractOwnerRepositoryTests {
 		
 }
\ No newline at end of file
-- 
GitLab