mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-05-29 14:49:38 +00:00
moved the ClinicRepository into some separate repos
There is still some polish up to be done.
This commit is contained in:
parent
16b1476c40
commit
c9c8c4e085
47 changed files with 1666 additions and 728 deletions
|
@ -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;
|
|
||||||
|
|
||||||
}
|
|
|
@ -126,19 +126,12 @@ public class Owner extends Person {
|
||||||
return new ToStringCreator(this)
|
return new ToStringCreator(this)
|
||||||
|
|
||||||
.append("id", this.getId())
|
.append("id", this.getId())
|
||||||
|
|
||||||
.append("new", this.isNew())
|
.append("new", this.isNew())
|
||||||
|
|
||||||
.append("lastName", this.getLastName())
|
.append("lastName", this.getLastName())
|
||||||
|
|
||||||
.append("firstName", this.getFirstName())
|
.append("firstName", this.getFirstName())
|
||||||
|
|
||||||
.append("address", this.address)
|
.append("address", this.address)
|
||||||
|
|
||||||
.append("city", this.city)
|
.append("city", this.city)
|
||||||
|
|
||||||
.append("telephone", this.telephone)
|
.append("telephone", this.telephone)
|
||||||
|
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import org.aspectj.lang.annotation.Before;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sample AspectJ annotation-style aspect that saves
|
* 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 Rod Johnson
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package org.springframework.samples.petclinic.jdbc;
|
package org.springframework.samples.petclinic.repository.jdbc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface that defines a cache refresh operation.
|
* Interface that defines a cache refresh operation.
|
||||||
|
@ -11,8 +11,8 @@ package org.springframework.samples.petclinic.jdbc;
|
||||||
public interface JdbcClinicImplMBean {
|
public interface JdbcClinicImplMBean {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refresh the cache of Vets that the Clinic is holding.
|
* Refresh the cache of Vets that the ClinicService is holding.
|
||||||
* @see org.springframework.samples.petclinic.Clinic#getVets()
|
* @see org.springframework.samples.petclinic.service.ClinicService#getVets()
|
||||||
* @see JdbcClinicImpl#refreshVetsCache()
|
* @see JdbcClinicImpl#refreshVetsCache()
|
||||||
*/
|
*/
|
||||||
void refreshVetsCache();
|
void refreshVetsCache();
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
package org.springframework.samples.petclinic.jdbc;
|
package org.springframework.samples.petclinic.repository.jdbc;
|
||||||
|
|
||||||
import org.springframework.samples.petclinic.Pet;
|
import org.springframework.samples.petclinic.Pet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of Pet that carries temporary id properties which
|
* 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
|
* @author Juergen Hoeller
|
||||||
* @see JdbcClinicImpl
|
* @see JdbcClinicImpl
|
|
@ -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}.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -5,5 +5,5 @@
|
||||||
* of PetClinic's persistence layer.
|
* of PetClinic's persistence layer.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package org.springframework.samples.petclinic.jdbc;
|
package org.springframework.samples.petclinic.repository.jdbc;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package org.springframework.samples.petclinic.jpa;
|
package org.springframework.samples.petclinic.repository.jpa;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
@ -6,18 +6,18 @@ import javax.persistence.EntityManager;
|
||||||
import javax.persistence.PersistenceContext;
|
import javax.persistence.PersistenceContext;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
|
|
||||||
import org.springframework.samples.petclinic.Clinic;
|
|
||||||
import org.springframework.samples.petclinic.Owner;
|
import org.springframework.samples.petclinic.Owner;
|
||||||
import org.springframework.samples.petclinic.Pet;
|
import org.springframework.samples.petclinic.Pet;
|
||||||
import org.springframework.samples.petclinic.PetType;
|
import org.springframework.samples.petclinic.PetType;
|
||||||
import org.springframework.samples.petclinic.Vet;
|
import org.springframework.samples.petclinic.Vet;
|
||||||
import org.springframework.samples.petclinic.Visit;
|
import org.springframework.samples.petclinic.Visit;
|
||||||
|
import org.springframework.samples.petclinic.service.ClinicService;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.dao.DataAccessException;
|
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.
|
* <p>The mappings are defined in "orm.xml" located in the META-INF directory.
|
||||||
*
|
*
|
||||||
|
@ -29,7 +29,7 @@ import org.springframework.dao.DataAccessException;
|
||||||
*/
|
*/
|
||||||
@Repository
|
@Repository
|
||||||
@Transactional
|
@Transactional
|
||||||
public class JpaClinicImpl implements Clinic {
|
public class JpaClinicImpl implements ClinicService {
|
||||||
|
|
||||||
@PersistenceContext
|
@PersistenceContext
|
||||||
private EntityManager em;
|
private EntityManager em;
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,22 +1,22 @@
|
||||||
package org.springframework.samples.petclinic.jpa;
|
package org.springframework.samples.petclinic.repository.jpa;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.Repository;
|
import org.springframework.data.repository.Repository;
|
||||||
import org.springframework.samples.petclinic.Clinic;
|
|
||||||
import org.springframework.samples.petclinic.Owner;
|
import org.springframework.samples.petclinic.Owner;
|
||||||
import org.springframework.samples.petclinic.Pet;
|
import org.springframework.samples.petclinic.Pet;
|
||||||
import org.springframework.samples.petclinic.PetType;
|
import org.springframework.samples.petclinic.PetType;
|
||||||
import org.springframework.samples.petclinic.Vet;
|
import org.springframework.samples.petclinic.Vet;
|
||||||
import org.springframework.samples.petclinic.Visit;
|
import org.springframework.samples.petclinic.Visit;
|
||||||
|
import org.springframework.samples.petclinic.service.ClinicService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Michael Isvy
|
* @author Michael Isvy
|
||||||
* @since 15.1.2013
|
* @since 15.1.2013
|
||||||
*/
|
*/
|
||||||
public interface SpringDataClinic extends Clinic, Repository {
|
public interface SpringDataClinic extends ClinicService, Repository {
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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> {
|
||||||
|
}
|
|
@ -5,5 +5,5 @@
|
||||||
* of PetClinic's persistence layer.
|
* of PetClinic's persistence layer.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package org.springframework.samples.petclinic.jpa;
|
package org.springframework.samples.petclinic.repository.jpa;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -6,8 +6,8 @@ import java.util.Date;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.propertyeditors.CustomDateEditor;
|
import org.springframework.beans.propertyeditors.CustomDateEditor;
|
||||||
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
|
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
|
||||||
import org.springframework.samples.petclinic.Clinic;
|
|
||||||
import org.springframework.samples.petclinic.PetType;
|
import org.springframework.samples.petclinic.PetType;
|
||||||
|
import org.springframework.samples.petclinic.service.ClinicService;
|
||||||
import org.springframework.web.bind.WebDataBinder;
|
import org.springframework.web.bind.WebDataBinder;
|
||||||
import org.springframework.web.bind.support.WebBindingInitializer;
|
import org.springframework.web.bind.support.WebBindingInitializer;
|
||||||
import org.springframework.web.context.request.WebRequest;
|
import org.springframework.web.context.request.WebRequest;
|
||||||
|
@ -24,14 +24,14 @@ import org.springframework.web.context.request.WebRequest;
|
||||||
public class ClinicBindingInitializer implements WebBindingInitializer {
|
public class ClinicBindingInitializer implements WebBindingInitializer {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private Clinic clinic;
|
private ClinicService clinicService;
|
||||||
|
|
||||||
public void initBinder(WebDataBinder binder, WebRequest request) {
|
public void initBinder(WebDataBinder binder, WebRequest request) {
|
||||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
dateFormat.setLenient(false);
|
dateFormat.setLenient(false);
|
||||||
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
|
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
|
||||||
binder.registerCustomEditor(String.class, new StringTrimmerEditor(false));
|
binder.registerCustomEditor(String.class, new StringTrimmerEditor(false));
|
||||||
binder.registerCustomEditor(PetType.class, new PetTypeEditor(this.clinic));
|
binder.registerCustomEditor(PetType.class, new PetTypeEditor(this.clinicService));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
|
||||||
* -> "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" -> "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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -6,8 +6,8 @@ import java.util.Collection;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.samples.petclinic.Clinic;
|
|
||||||
import org.springframework.samples.petclinic.Owner;
|
import org.springframework.samples.petclinic.Owner;
|
||||||
|
import org.springframework.samples.petclinic.repository.OwnerRepository;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.validation.BindingResult;
|
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.RequestMethod;
|
||||||
import org.springframework.web.bind.annotation.SessionAttributes;
|
import org.springframework.web.bind.annotation.SessionAttributes;
|
||||||
import org.springframework.web.bind.support.SessionStatus;
|
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 .
|
* 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)
|
@SessionAttributes(types = Owner.class)
|
||||||
public class OwnerController {
|
public class OwnerController {
|
||||||
|
|
||||||
private final Clinic clinic;
|
private final OwnerRepository ownerRepository;
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public OwnerController(Clinic clinic) {
|
public OwnerController(OwnerRepository ownerRepository) {
|
||||||
this.clinic = clinic;
|
this.ownerRepository = ownerRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@InitBinder
|
@InitBinder
|
||||||
|
@ -57,7 +58,7 @@ public class OwnerController {
|
||||||
return "owners/createOrUpdateOwnerForm";
|
return "owners/createOrUpdateOwnerForm";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.clinic.storeOwner(owner);
|
this.ownerRepository.save(owner);
|
||||||
status.setComplete();
|
status.setComplete();
|
||||||
return "redirect:/owners/" + owner.getId();
|
return "redirect:/owners/" + owner.getId();
|
||||||
}
|
}
|
||||||
|
@ -78,7 +79,7 @@ public class OwnerController {
|
||||||
}
|
}
|
||||||
|
|
||||||
// find owners by last name
|
// 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) {
|
if (results.size() < 1) {
|
||||||
// no owners found
|
// no owners found
|
||||||
result.rejectValue("lastName", "notFound", "not found");
|
result.rejectValue("lastName", "notFound", "not found");
|
||||||
|
@ -98,7 +99,7 @@ public class OwnerController {
|
||||||
|
|
||||||
@RequestMapping(value="/owners/{ownerId}/edit", method = RequestMethod.GET)
|
@RequestMapping(value="/owners/{ownerId}/edit", method = RequestMethod.GET)
|
||||||
public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) {
|
public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) {
|
||||||
Owner owner = this.clinic.findOwner(ownerId);
|
Owner owner = this.ownerRepository.findById(ownerId);
|
||||||
model.addAttribute(owner);
|
model.addAttribute(owner);
|
||||||
return "owners/createOrUpdateOwnerForm";
|
return "owners/createOrUpdateOwnerForm";
|
||||||
}
|
}
|
||||||
|
@ -109,10 +110,23 @@ public class OwnerController {
|
||||||
return "owners/createOrUpdateOwnerForm";
|
return "owners/createOrUpdateOwnerForm";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.clinic.storeOwner(owner);
|
this.ownerRepository.save(owner);
|
||||||
status.setComplete();
|
status.setComplete();
|
||||||
return "redirect:/owners/" + owner.getId();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,10 @@ package org.springframework.samples.petclinic.web;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.samples.petclinic.Clinic;
|
|
||||||
import org.springframework.samples.petclinic.Owner;
|
import org.springframework.samples.petclinic.Owner;
|
||||||
import org.springframework.samples.petclinic.Pet;
|
import org.springframework.samples.petclinic.Pet;
|
||||||
import org.springframework.samples.petclinic.PetType;
|
import org.springframework.samples.petclinic.PetType;
|
||||||
|
import org.springframework.samples.petclinic.service.ClinicService;
|
||||||
import org.springframework.samples.petclinic.validation.PetValidator;
|
import org.springframework.samples.petclinic.validation.PetValidator;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
|
@ -33,17 +33,17 @@ import org.springframework.web.bind.support.SessionStatus;
|
||||||
@SessionAttributes("pet")
|
@SessionAttributes("pet")
|
||||||
public class PetController {
|
public class PetController {
|
||||||
|
|
||||||
private final Clinic clinic;
|
private final ClinicService clinicService;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public PetController(Clinic clinic) {
|
public PetController(ClinicService clinicService) {
|
||||||
this.clinic = clinic;
|
this.clinicService = clinicService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ModelAttribute("types")
|
@ModelAttribute("types")
|
||||||
public Collection<PetType> populatePetTypes() {
|
public Collection<PetType> populatePetTypes() {
|
||||||
return this.clinic.getPetTypes();
|
return this.clinicService.getPetTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
@InitBinder
|
@InitBinder
|
||||||
|
@ -53,7 +53,7 @@ public class PetController {
|
||||||
|
|
||||||
@RequestMapping(value="/owners/{ownerId}/pets/new", method = RequestMethod.GET)
|
@RequestMapping(value="/owners/{ownerId}/pets/new", method = RequestMethod.GET)
|
||||||
public String initCreationForm(@PathVariable("ownerId") int ownerId, Model model) {
|
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();
|
Pet pet = new Pet();
|
||||||
owner.addPet(pet);
|
owner.addPet(pet);
|
||||||
model.addAttribute("pet", pet);
|
model.addAttribute("pet", pet);
|
||||||
|
@ -67,7 +67,7 @@ public class PetController {
|
||||||
return "pets/createOrUpdatePetForm";
|
return "pets/createOrUpdatePetForm";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.clinic.storePet(pet);
|
this.clinicService.storePet(pet);
|
||||||
status.setComplete();
|
status.setComplete();
|
||||||
return "redirect:/owners/" + pet.getOwner().getId();
|
return "redirect:/owners/" + pet.getOwner().getId();
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ public class PetController {
|
||||||
|
|
||||||
@RequestMapping(value="/owners/*/pets/{petId}/edit", method = RequestMethod.GET)
|
@RequestMapping(value="/owners/*/pets/{petId}/edit", method = RequestMethod.GET)
|
||||||
public String initUpdateForm(@PathVariable("petId") int petId, Model model) {
|
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);
|
model.addAttribute("pet", pet);
|
||||||
return "pets/createOrUpdatePetForm";
|
return "pets/createOrUpdatePetForm";
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ public class PetController {
|
||||||
return "pets/createOrUpdatePetForm";
|
return "pets/createOrUpdatePetForm";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.clinic.storePet(pet);
|
this.clinicService.storePet(pet);
|
||||||
status.setComplete();
|
status.setComplete();
|
||||||
return "redirect:/owners/" + pet.getOwner().getId();
|
return "redirect:/owners/" + pet.getOwner().getId();
|
||||||
}
|
}
|
||||||
|
@ -96,8 +96,8 @@ public class PetController {
|
||||||
|
|
||||||
@RequestMapping(value="/owners/*/pets/{petId}/edit", method = RequestMethod.DELETE)
|
@RequestMapping(value="/owners/*/pets/{petId}/edit", method = RequestMethod.DELETE)
|
||||||
public String deletePet(@PathVariable("petId") int petId) {
|
public String deletePet(@PathVariable("petId") int petId) {
|
||||||
Pet pet = this.clinic.findPet(petId);
|
Pet pet = this.clinicService.findPetById(petId);
|
||||||
this.clinic.deletePet(petId);
|
this.clinicService.deletePet(petId);
|
||||||
return "redirect:/owners/" + pet.getOwner().getId();
|
return "redirect:/owners/" + pet.getOwner().getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@ package org.springframework.samples.petclinic.web;
|
||||||
|
|
||||||
import java.beans.PropertyEditorSupport;
|
import java.beans.PropertyEditorSupport;
|
||||||
|
|
||||||
import org.springframework.samples.petclinic.Clinic;
|
|
||||||
import org.springframework.samples.petclinic.PetType;
|
import org.springframework.samples.petclinic.PetType;
|
||||||
|
import org.springframework.samples.petclinic.service.ClinicService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Mark Fisher
|
* @author Mark Fisher
|
||||||
|
@ -11,16 +11,16 @@ import org.springframework.samples.petclinic.PetType;
|
||||||
*/
|
*/
|
||||||
public class PetTypeEditor extends PropertyEditorSupport {
|
public class PetTypeEditor extends PropertyEditorSupport {
|
||||||
|
|
||||||
private final Clinic clinic;
|
private final ClinicService clinicService;
|
||||||
|
|
||||||
|
|
||||||
public PetTypeEditor(Clinic clinic) {
|
public PetTypeEditor(ClinicService clinicService) {
|
||||||
this.clinic = clinic;
|
this.clinicService = clinicService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAsText(String text) throws IllegalArgumentException {
|
public void setAsText(String text) throws IllegalArgumentException {
|
||||||
for (PetType type : this.clinic.getPetTypes()) {
|
for (PetType type : this.clinicService.getPetTypes()) {
|
||||||
if (type.getName().equals(text)) {
|
if (type.getName().equals(text)) {
|
||||||
setValue(type);
|
setValue(type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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" -> "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";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -4,9 +4,9 @@ package org.springframework.samples.petclinic.web;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.samples.petclinic.Clinic;
|
|
||||||
import org.springframework.samples.petclinic.Pet;
|
import org.springframework.samples.petclinic.Pet;
|
||||||
import org.springframework.samples.petclinic.Visit;
|
import org.springframework.samples.petclinic.Visit;
|
||||||
|
import org.springframework.samples.petclinic.service.ClinicService;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.validation.BindingResult;
|
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.RequestMethod;
|
||||||
import org.springframework.web.bind.annotation.SessionAttributes;
|
import org.springframework.web.bind.annotation.SessionAttributes;
|
||||||
import org.springframework.web.bind.support.SessionStatus;
|
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
|
* 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")
|
@SessionAttributes("visit")
|
||||||
public class VisitController {
|
public class VisitController {
|
||||||
|
|
||||||
private final Clinic clinic;
|
private final ClinicService clinicService;
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public VisitController(Clinic clinic) {
|
public VisitController(ClinicService clinicService) {
|
||||||
this.clinic = clinic;
|
this.clinicService = clinicService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@InitBinder
|
@InitBinder
|
||||||
|
@ -44,8 +45,8 @@ public class VisitController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value="/owners/*/pets/{petId}/visits/new", method = RequestMethod.GET)
|
@RequestMapping(value="/owners/*/pets/{petId}/visits/new", method = RequestMethod.GET)
|
||||||
public String setupForm(@PathVariable("petId") int petId, Model model) {
|
public String initNewVisitForm(@PathVariable("petId") int petId, Model model) {
|
||||||
Pet pet = this.clinic.findPet(petId);
|
Pet pet = this.clinicService.findPetById(petId);
|
||||||
Visit visit = new Visit();
|
Visit visit = new Visit();
|
||||||
pet.addVisit(visit);
|
pet.addVisit(visit);
|
||||||
model.addAttribute("visit", visit);
|
model.addAttribute("visit", visit);
|
||||||
|
@ -53,15 +54,28 @@ public class VisitController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value="/owners/*/pets/{petId}/visits/new", method = RequestMethod.POST)
|
@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()) {
|
if (result.hasErrors()) {
|
||||||
return "pets/createOrUpdateVisitForm";
|
return "pets/createOrUpdateVisitForm";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.clinic.storeVisit(visit);
|
this.clinicService.storeVisit(visit);
|
||||||
status.setComplete();
|
status.setComplete();
|
||||||
return "redirect:/owners/" + visit.getPet().getOwner().getId();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class VisitsAtomView extends AbstractAtomFeedView {
|
||||||
@Override
|
@Override
|
||||||
protected void buildFeedMetadata(Map<String, Object> model, Feed feed, HttpServletRequest request) {
|
protected void buildFeedMetadata(Map<String, Object> model, Feed feed, HttpServletRequest request) {
|
||||||
feed.setId("tag:springsource.com");
|
feed.setId("tag:springsource.com");
|
||||||
feed.setTitle("Pet Clinic Visits");
|
feed.setTitle("Pet ClinicService Visits");
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
List<Visit> visits = (List<Visit>) model.get("visits");
|
List<Visit> visits = (List<Visit>) model.get("visits");
|
||||||
for (Visit visit : visits) {
|
for (Visit visit : visits) {
|
||||||
|
|
|
@ -96,10 +96,16 @@
|
||||||
<!-- Transaction manager for a single JDBC DataSource (alternative to JTA) -->
|
<!-- Transaction manager for a single JDBC DataSource (alternative to JTA) -->
|
||||||
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
|
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
|
||||||
p:dataSource-ref="dataSource"/>
|
p:dataSource-ref="dataSource"/>
|
||||||
|
|
||||||
|
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
|
||||||
<!-- PetClinic's central data access object using Spring's SimpleJdbcTemplate -->
|
<constructor-arg ref="dataSource" />
|
||||||
<bean id="clinic" class="org.springframework.samples.petclinic.jdbc.JdbcClinicImpl"/>
|
</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>
|
</beans>
|
||||||
|
|
||||||
|
@ -109,12 +115,12 @@
|
||||||
EntityManager will be auto-injected due to @PersistenceContext.
|
EntityManager will be auto-injected due to @PersistenceContext.
|
||||||
PersistenceExceptions will be auto-translated due to @Repository.
|
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>
|
||||||
|
|
||||||
<beans profile="spring-data-jpa">
|
<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>
|
||||||
</beans>
|
</beans>
|
|
@ -13,7 +13,7 @@
|
||||||
<!--
|
<!--
|
||||||
- The controllers are autodetected POJOs labeled with the @Controller annotation.
|
- 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 />
|
<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) -->
|
<!-- 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: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,
|
- This view resolver delegates to the InternalResourceViewResolver and BeanNameViewResolver,
|
||||||
|
|
|
@ -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>
|
||||||
|
* "AbstractClinicTests-context.xml" 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -8,6 +8,9 @@ import static org.junit.Assert.assertTrue;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.samples.petclinic.util.EntityUtils;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
|
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
|
||||||
|
@ -15,14 +18,14 @@ import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Base class for {@link Clinic} integration tests.
|
* Base class for {@link ClinicService} integration tests.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* "AbstractClinicTests-context.xml" declares a common
|
* "AbstractClinicTests-context.xml" declares a common
|
||||||
* {@link javax.sql.DataSource DataSource}. Subclasses should specify
|
* {@link javax.sql.DataSource DataSource}. Subclasses should specify
|
||||||
* additional context locations which declare a
|
* additional context locations which declare a
|
||||||
* {@link org.springframework.transaction.PlatformTransactionManager PlatformTransactionManager}
|
* {@link org.springframework.transaction.PlatformTransactionManager PlatformTransactionManager}
|
||||||
* and a concrete implementation of {@link Clinic}.
|
* and a concrete implementation of {@link ClinicService}.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* This class extends {@link AbstractTransactionalJUnit4SpringContextTests},
|
* This class extends {@link AbstractTransactionalJUnit4SpringContextTests},
|
||||||
|
@ -48,9 +51,9 @@ import org.springframework.transaction.annotation.Transactional;
|
||||||
* unnecessary set up time between test execution.</li>
|
* unnecessary set up time between test execution.</li>
|
||||||
* <li><strong>Dependency Injection</strong> of test fixture instances,
|
* <li><strong>Dependency Injection</strong> of test fixture instances,
|
||||||
* meaning that we don't need to perform application context lookups. See the
|
* 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
|
* 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
|
* {@link javax.annotation.Resource @Resource} to achieve dependency injection
|
||||||
* <em>by name</em>.
|
* <em>by name</em>.
|
||||||
* <em>(see: {@link ContextConfiguration @ContextConfiguration},
|
* <em>(see: {@link ContextConfiguration @ContextConfiguration},
|
||||||
|
@ -81,30 +84,18 @@ import org.springframework.transaction.annotation.Transactional;
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @author Sam Brannen
|
* @author Sam Brannen
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractClinicTests {
|
public abstract class AbstractPetRepositoryTests {
|
||||||
|
|
||||||
@Autowired
|
@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
|
@Test
|
||||||
public void getPetTypes() {
|
public void getPetTypes() {
|
||||||
Collection<PetType> petTypes = this.clinic.getPetTypes();
|
Collection<PetType> petTypes = this.petRepository.getPetTypes();
|
||||||
|
|
||||||
PetType t1 = EntityUtils.getById(petTypes, PetType.class, 1);
|
PetType t1 = EntityUtils.getById(petTypes, PetType.class, 1);
|
||||||
assertEquals("cat", t1.getName());
|
assertEquals("cat", t1.getName());
|
||||||
|
@ -112,63 +103,14 @@ public abstract class AbstractClinicTests {
|
||||||
assertEquals("snake", t4.getName());
|
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
|
@Test
|
||||||
public void findPet() {
|
public void findPet() {
|
||||||
Collection<PetType> types = this.clinic.getPetTypes();
|
Collection<PetType> types = this.petRepository.getPetTypes();
|
||||||
Pet p7 = this.clinic.findPet(7);
|
Pet p7 = this.petRepository.findById(7);
|
||||||
assertTrue(p7.getName().startsWith("Samantha"));
|
assertTrue(p7.getName().startsWith("Samantha"));
|
||||||
assertEquals(EntityUtils.getById(types, PetType.class, 1).getId(), p7.getType().getId());
|
assertEquals(EntityUtils.getById(types, PetType.class, 1).getId(), p7.getType().getId());
|
||||||
assertEquals("Jean", p7.getOwner().getFirstName());
|
assertEquals("Jean", p7.getOwner().getFirstName());
|
||||||
Pet p6 = this.clinic.findPet(6);
|
Pet p6 = this.petRepository.findById(6);
|
||||||
assertEquals("George", p6.getName());
|
assertEquals("George", p6.getName());
|
||||||
assertEquals(EntityUtils.getById(types, PetType.class, 4).getId(), p6.getType().getId());
|
assertEquals(EntityUtils.getById(types, PetType.class, 4).getId(), p6.getType().getId());
|
||||||
assertEquals("Peter", p6.getOwner().getFirstName());
|
assertEquals("Peter", p6.getOwner().getFirstName());
|
||||||
|
@ -176,46 +118,30 @@ public abstract class AbstractClinicTests {
|
||||||
|
|
||||||
@Test @Transactional
|
@Test @Transactional
|
||||||
public void insertPet() {
|
public void insertPet() {
|
||||||
Owner o6 = this.clinic.findOwner(6);
|
Owner o6 = this.ownerRepository.findById(6);
|
||||||
int found = o6.getPets().size();
|
int found = o6.getPets().size();
|
||||||
Pet pet = new Pet();
|
Pet pet = new Pet();
|
||||||
pet.setName("bowser");
|
pet.setName("bowser");
|
||||||
Collection<PetType> types = this.clinic.getPetTypes();
|
Collection<PetType> types = this.petRepository.getPetTypes();
|
||||||
pet.setType(EntityUtils.getById(types, PetType.class, 2));
|
pet.setType(EntityUtils.getById(types, PetType.class, 2));
|
||||||
pet.setBirthDate(new Date());
|
pet.setBirthDate(new Date());
|
||||||
o6.addPet(pet);
|
o6.addPet(pet);
|
||||||
assertEquals(found + 1, o6.getPets().size());
|
assertEquals(found + 1, o6.getPets().size());
|
||||||
// both storePet and storeOwner are necessary to cover all ORM tools
|
// both storePet and storeOwner are necessary to cover all ORM tools
|
||||||
this.clinic.storePet(pet);
|
this.petRepository.storePet(pet);
|
||||||
this.clinic.storeOwner(o6);
|
this.ownerRepository.save(o6);
|
||||||
// assertTrue(!pet.isNew()); -- NOT TRUE FOR TOPLINK (before commit)
|
o6 = this.ownerRepository.findById(6);
|
||||||
o6 = this.clinic.findOwner(6);
|
|
||||||
assertEquals(found + 1, o6.getPets().size());
|
assertEquals(found + 1, o6.getPets().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void updatePet() throws Exception {
|
public void updatePet() throws Exception {
|
||||||
Pet p7 = this.clinic.findPet(7);
|
Pet p7 = this.petRepository.findById(7);
|
||||||
String old = p7.getName();
|
String old = p7.getName();
|
||||||
p7.setName(old + "X");
|
p7.setName(old + "X");
|
||||||
this.clinic.storePet(p7);
|
this.petRepository.storePet(p7);
|
||||||
p7 = this.clinic.findPet(7);
|
p7 = this.petRepository.findById(7);
|
||||||
assertEquals(old + "X", p7.getName());
|
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -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>
|
||||||
|
* "AbstractClinicTests-context.xml" 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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>
|
||||||
|
* "AbstractClinicTests-context.xml" 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,18 +1,17 @@
|
||||||
package org.springframework.samples.petclinic.aspects;
|
package org.springframework.samples.petclinic.aspects;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertFalse;
|
||||||
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.samples.petclinic.Clinic;
|
import org.springframework.samples.petclinic.repository.OwnerRepository;
|
||||||
import org.springframework.samples.petclinic.aspects.UsageLogAspect;
|
|
||||||
import org.springframework.samples.petclinic.jpa.JpaClinicImplTests;
|
|
||||||
import org.springframework.test.context.ActiveProfiles;
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
import static junit.framework.Assert.assertTrue;
|
|
||||||
import static junit.framework.Assert.assertFalse;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -36,7 +35,7 @@ public class UsageLogAspectTests {
|
||||||
private UsageLogAspect usageLogAspect;
|
private UsageLogAspect usageLogAspect;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private Clinic clinic;
|
private OwnerRepository ownerRepository;
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -45,8 +44,8 @@ public class UsageLogAspectTests {
|
||||||
String lastName2 = "Davis";
|
String lastName2 = "Davis";
|
||||||
String lastName3 = "foo";
|
String lastName3 = "foo";
|
||||||
|
|
||||||
assertFalse(this.clinic.findOwners(lastName1).isEmpty());
|
assertFalse(this.ownerRepository.findByLastName(lastName1).isEmpty());
|
||||||
assertFalse(this.clinic.findOwners(lastName2).isEmpty());
|
assertFalse(this.ownerRepository.findByLastName(lastName2).isEmpty());
|
||||||
|
|
||||||
List<String> namesRequested = this.usageLogAspect.getNamesRequested();
|
List<String> namesRequested = this.usageLogAspect.getNamesRequested();
|
||||||
assertTrue(namesRequested.contains(lastName1));
|
assertTrue(namesRequested.contains(lastName1));
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
package org.springframework.samples.petclinic.jdbc;
|
package org.springframework.samples.petclinic.jdbc;
|
||||||
|
|
||||||
import org.junit.runner.RunWith;
|
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.annotation.DirtiesContext;
|
||||||
import org.springframework.test.context.ActiveProfiles;
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
@ -21,7 +22,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@DirtiesContext
|
@DirtiesContext
|
||||||
@ActiveProfiles("jdbc")
|
@ActiveProfiles("jdbc")
|
||||||
public class JdbcClinicImplTests extends AbstractClinicTests {
|
public class JdbcPetRepositoryImplTests extends AbstractPetRepositoryTests {
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,16 +1,8 @@
|
||||||
|
|
||||||
package org.springframework.samples.petclinic.jpa;
|
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.junit.runner.RunWith;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.samples.petclinic.AbstractOwnerRepositoryTests;
|
||||||
import org.springframework.samples.petclinic.AbstractClinicTests;
|
|
||||||
import org.springframework.samples.petclinic.Clinic;
|
|
||||||
import org.springframework.test.context.ActiveProfiles;
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
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"})
|
@ContextConfiguration(locations={"classpath:spring/applicationContext-dao.xml"})
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ActiveProfiles({"jpa","plain-jpa"})
|
@ActiveProfiles({"jpa","plain-jpa"})
|
||||||
public class JpaClinicImplTests extends AbstractClinicTests {
|
public class JpaOwnerRepositoryImplTests extends AbstractOwnerRepositoryTests {
|
||||||
|
|
||||||
@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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
package org.springframework.samples.petclinic.jpa;
|
package org.springframework.samples.petclinic.jpa;
|
||||||
|
|
||||||
import org.junit.runner.RunWith;
|
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.ActiveProfiles;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
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"})
|
@ContextConfiguration(locations={"classpath:spring/applicationContext-dao.xml"})
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ActiveProfiles({"jpa","spring-data-jpa"})
|
@ActiveProfiles({"jpa","spring-data-jpa"})
|
||||||
public class SpringDataClinicTests extends AbstractClinicTests {
|
public class SpringDataOwnerRepositoryTests extends AbstractOwnerRepositoryTests {
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue