From 76271709ec7fd08d03bbe912d7ec686c20e63259 Mon Sep 17 00:00:00 2001 From: Antoine Rey Date: Wed, 27 Dec 2023 12:15:28 +0100 Subject: [PATCH] Migrate Jdbc DAO from RestTemplate to JdbcClient #103 --- pom.xml | 2 +- .../jdbc/JdbcOwnerRepositoryImpl.java | 82 +++++++++---------- .../jdbc/JdbcPetRepositoryImpl.java | 53 ++++++------ .../jdbc/JdbcVetRepositoryImpl.java | 53 ++++++------ .../jdbc/JdbcVisitRepositoryImpl.java | 34 ++++---- src/main/resources/spring/business-config.xml | 3 +- 6 files changed, 116 insertions(+), 111 deletions(-) diff --git a/pom.xml b/pom.xml index 66d99ab55..423191921 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 org.springframework.samples spring-framework-petclinic - 6.0.15 + 6.1.2 Spring Framework Petclinic war diff --git a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcOwnerRepositoryImpl.java b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcOwnerRepositoryImpl.java index 4b6f14f81..776a29cf6 100644 --- a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcOwnerRepositoryImpl.java +++ b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcOwnerRepositoryImpl.java @@ -15,18 +15,11 @@ */ package org.springframework.samples.petclinic.repository.jdbc; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.sql.DataSource; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.simple.JdbcClient; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.orm.ObjectRetrievalFailureException; import org.springframework.samples.petclinic.model.Owner; @@ -37,6 +30,10 @@ import org.springframework.samples.petclinic.util.EntityUtils; import org.springframework.stereotype.Repository; +import javax.sql.DataSource; +import java.util.Collection; +import java.util.List; + /** * A simple JDBC-based implementation of the {@link OwnerRepository} interface. * @@ -51,18 +48,18 @@ @Repository public class JdbcOwnerRepositoryImpl implements OwnerRepository { - private NamedParameterJdbcTemplate namedParameterJdbcTemplate; + private final JdbcClient jdbcClient; - private SimpleJdbcInsert insertOwner; + private final SimpleJdbcInsert insertOwner; @Autowired - public JdbcOwnerRepositoryImpl(DataSource dataSource) { + public JdbcOwnerRepositoryImpl(DataSource dataSource, JdbcClient jdbcClient) { this.insertOwner = new SimpleJdbcInsert(dataSource) .withTableName("owners") .usingGeneratedKeyColumns("id"); - this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); + this.jdbcClient = jdbcClient; } @@ -74,13 +71,14 @@ public JdbcOwnerRepositoryImpl(DataSource dataSource) { */ @Override public Collection findByLastName(String lastName) { - Map params = new HashMap<>(); - params.put("lastName", lastName + "%"); - List owners = this.namedParameterJdbcTemplate.query( - "SELECT id, first_name, last_name, address, city, telephone FROM owners WHERE last_name like :lastName", - params, - BeanPropertyRowMapper.newInstance(Owner.class) - ); + List owners = this.jdbcClient.sql(""" + SELECT id, first_name, last_name, address, city, telephone + FROM owners + WHERE last_name like :lastName + """) + .param("lastName", lastName + "%") + .query(BeanPropertyRowMapper.newInstance(Owner.class)) + .list(); loadOwnersPetsAndVisits(owners); return owners; } @@ -93,13 +91,13 @@ public Collection findByLastName(String lastName) { public Owner findById(int id) { Owner owner; try { - Map params = new HashMap<>(); - params.put("id", id); - owner = this.namedParameterJdbcTemplate.queryForObject( - "SELECT id, first_name, last_name, address, city, telephone FROM owners WHERE id= :id", - params, - BeanPropertyRowMapper.newInstance(Owner.class) - ); + owner = this.jdbcClient.sql(""" + SELECT id, first_name, last_name, address, city, telephone + FROM owners WHERE id = :id + """) + .param("id", id) + .query(BeanPropertyRowMapper.newInstance(Owner.class)) + .single(); } catch (EmptyResultDataAccessException ex) { throw new ObjectRetrievalFailureException(Owner.class, id); } @@ -108,13 +106,13 @@ public Owner findById(int id) { } public void loadPetsAndVisits(final Owner owner) { - Map params = new HashMap<>(); - params.put("id", owner.getId()); - final List pets = this.namedParameterJdbcTemplate.query( - "SELECT pets.id, name, birth_date, type_id, owner_id, visits.id as visit_id, visit_date, description, pet_id FROM pets LEFT OUTER JOIN visits ON pets.id = pet_id WHERE owner_id=:id ORDER BY pet_id", - params, - new JdbcPetVisitExtractor() - ); + final List pets = this.jdbcClient.sql(""" + SELECT pets.id, name, birth_date, type_id, owner_id, visits.id as visit_id, visit_date, description, pet_id + FROM pets LEFT OUTER JOIN visits ON pets.id = pet_id + WHERE owner_id=:id ORDER BY pet_id + """) + .param("id", owner.getId()) + .query(new JdbcPetVisitExtractor()); Collection petTypes = getPetTypes(); for (JdbcPet pet : pets) { pet.setType(EntityUtils.getById(petTypes, PetType.class, pet.getTypeId())); @@ -129,17 +127,20 @@ public void save(Owner owner) { Number newKey = this.insertOwner.executeAndReturnKey(parameterSource); 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", - parameterSource); + this.jdbcClient.sql(""" + UPDATE owners + SET first_name=:firstName, last_name=:lastName, address=:address, city=:city, telephone=:telephone + WHERE id=:id + """) + .paramSource(parameterSource) + .update(); } } public Collection getPetTypes() { - return this.namedParameterJdbcTemplate.query( - "SELECT id, name FROM types ORDER BY name", new HashMap(), - BeanPropertyRowMapper.newInstance(PetType.class)); + return this.jdbcClient.sql("SELECT id, name FROM types ORDER BY name") + .query(BeanPropertyRowMapper.newInstance(PetType.class)) + .list(); } /** @@ -154,5 +155,4 @@ private void loadOwnersPetsAndVisits(List owners) { } } - } diff --git a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcPetRepositoryImpl.java b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcPetRepositoryImpl.java index c09311481..f2d2cc737 100644 --- a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcPetRepositoryImpl.java +++ b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcPetRepositoryImpl.java @@ -15,17 +15,11 @@ */ package org.springframework.samples.petclinic.repository.jdbc; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.sql.DataSource; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.simple.JdbcClient; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.orm.ObjectRetrievalFailureException; import org.springframework.samples.petclinic.model.Owner; @@ -36,6 +30,9 @@ import org.springframework.samples.petclinic.util.EntityUtils; import org.springframework.stereotype.Repository; +import javax.sql.DataSource; +import java.util.List; + /** * @author Ken Krebs * @author Juergen Hoeller @@ -43,19 +40,20 @@ * @author Sam Brannen * @author Thomas Risberg * @author Mark Fisher + * @author Antoine Rey */ @Repository public class JdbcPetRepositoryImpl implements PetRepository { - private NamedParameterJdbcTemplate namedParameterJdbcTemplate; + private final JdbcClient jdbcClient; - private SimpleJdbcInsert insertPet; + private final SimpleJdbcInsert insertPet; - private OwnerRepository ownerRepository; + private final OwnerRepository ownerRepository; @Autowired - public JdbcPetRepositoryImpl(DataSource dataSource, OwnerRepository ownerRepository) { - this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); + public JdbcPetRepositoryImpl(JdbcClient jdbcClient, DataSource dataSource, OwnerRepository ownerRepository) { + this.jdbcClient = jdbcClient; this.insertPet = new SimpleJdbcInsert(dataSource) .withTableName("pets") @@ -66,20 +64,21 @@ public JdbcPetRepositoryImpl(DataSource dataSource, OwnerRepository ownerReposit @Override public List findPetTypes() { - Map params = new HashMap<>(); - return this.namedParameterJdbcTemplate.query( - "SELECT id, name FROM types ORDER BY name", - params, - BeanPropertyRowMapper.newInstance(PetType.class)); + return this.jdbcClient + .sql("SELECT id, name FROM types ORDER BY name") + .query(BeanPropertyRowMapper.newInstance(PetType.class)) + .list(); } @Override public Pet findById(int id) { - Integer ownerId; + int ownerId; try { - Map params = new HashMap<>(); - params.put("id", id); - ownerId = this.namedParameterJdbcTemplate.queryForObject("SELECT owner_id FROM pets WHERE id=:id", params, Integer.class); + ownerId = this.jdbcClient + .sql("SELECT owner_id FROM pets WHERE id=:id") + .param("id", id) + .query(Integer.class) + .single(); } catch (EmptyResultDataAccessException ex) { throw new ObjectRetrievalFailureException(Pet.class, id); } @@ -94,10 +93,14 @@ public void save(Pet pet) { 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)); + this.jdbcClient + .sql(""" + UPDATE pets + SET name=:name, birth_date=:birth_date, type_id=:type_id, owner_id=:owner_id + WHERE id=:id + """) + .paramSource(createPetParameterSource(pet)) + .update(); } } diff --git a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVetRepositoryImpl.java b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVetRepositoryImpl.java index e8ab69050..aabbc5ccb 100644 --- a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVetRepositoryImpl.java +++ b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVetRepositoryImpl.java @@ -15,21 +15,21 @@ */ 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 org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; -import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.simple.JdbcClient; import org.springframework.samples.petclinic.model.Specialty; import org.springframework.samples.petclinic.model.Vet; import org.springframework.samples.petclinic.repository.VetRepository; import org.springframework.samples.petclinic.util.EntityUtils; import org.springframework.stereotype.Repository; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + /** * A simple JDBC-based implementation of the {@link VetRepository} interface. * @@ -40,15 +40,16 @@ * @author Thomas Risberg * @author Mark Fisher * @author Michael Isvy + * @author Antoine Rey */ @Repository public class JdbcVetRepositoryImpl implements VetRepository { - private JdbcTemplate jdbcTemplate; + private final JdbcClient jdbcClient; @Autowired - public JdbcVetRepositoryImpl(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; + public JdbcVetRepositoryImpl(JdbcClient jdbcClient) { + this.jdbcClient = jdbcClient; } /** @@ -56,28 +57,30 @@ public JdbcVetRepositoryImpl(JdbcTemplate jdbcTemplate) { */ @Override public Collection findAll() { - List vets = new ArrayList<>(); // Retrieve the list of all vets. - vets.addAll(this.jdbcTemplate.query( - "SELECT id, first_name, last_name FROM vets ORDER BY last_name,first_name", - BeanPropertyRowMapper.newInstance(Vet.class))); + List vets = new ArrayList<>(this.jdbcClient.sql( + "SELECT id, first_name, last_name FROM vets ORDER BY last_name,first_name") + .query(BeanPropertyRowMapper.newInstance(Vet.class)) + .list()); // Retrieve the list of all possible specialties. - final List specialties = this.jdbcTemplate.query( - "SELECT id, name FROM specialties", - BeanPropertyRowMapper.newInstance(Specialty.class)); + final List specialties = this.jdbcClient.sql("SELECT id, name FROM specialties") + .query(BeanPropertyRowMapper.newInstance(Specialty.class)) + .list(); // Build each vet's list of specialties. for (Vet vet : vets) { - final List vetSpecialtiesIds = this.jdbcTemplate.query( - "SELECT specialty_id FROM vet_specialties WHERE vet_id=?", - new BeanPropertyRowMapper() { - @Override - public Integer mapRow(ResultSet rs, int row) throws SQLException { - return rs.getInt(1); + final List vetSpecialtiesIds = this.jdbcClient.sql( + "SELECT specialty_id FROM vet_specialties WHERE vet_id=?") + .param(vet.getId()) + .query( + new BeanPropertyRowMapper() { + @Override + public Integer mapRow(ResultSet rs, int row) throws SQLException { + return rs.getInt(1); + } } - }, - vet.getId()); + ).list(); for (int specialtyId : vetSpecialtiesIds) { Specialty specialty = EntityUtils.getById(specialties, Specialty.class, specialtyId); vet.addSpecialty(specialty); diff --git a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVisitRepositoryImpl.java b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVisitRepositoryImpl.java index 68af7b4b7..994d58c0a 100644 --- a/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVisitRepositoryImpl.java +++ b/src/main/java/org/springframework/samples/petclinic/repository/jdbc/JdbcVisitRepositoryImpl.java @@ -17,17 +17,14 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.simple.JdbcClient; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.samples.petclinic.model.Visit; import org.springframework.samples.petclinic.repository.VisitRepository; import org.springframework.stereotype.Repository; import javax.sql.DataSource; - -import java.util.HashMap; import java.util.List; -import java.util.Map; /** * A simple JDBC-based implementation of the {@link VisitRepository} interface. @@ -43,13 +40,13 @@ @Repository public class JdbcVisitRepositoryImpl implements VisitRepository { - private NamedParameterJdbcTemplate jdbcTemplate; + private final JdbcClient jdbcClient; - private SimpleJdbcInsert insertVisit; + private final SimpleJdbcInsert insertVisit; @Autowired - public JdbcVisitRepositoryImpl(DataSource dataSource) { - this.jdbcTemplate = new NamedParameterJdbcTemplate(dataSource); + public JdbcVisitRepositoryImpl(DataSource dataSource, JdbcClient jdbcClient) { + this.jdbcClient = jdbcClient; this.insertVisit = new SimpleJdbcInsert(dataSource) .withTableName("visits") @@ -82,16 +79,17 @@ private MapSqlParameterSource createVisitParameterSource(Visit visit) { @Override public List findByPetId(Integer petId) { - Map params = new HashMap<>(); - params.put("id", petId); - JdbcPet pet = this.jdbcTemplate.queryForObject( - "SELECT id, name, birth_date, type_id, owner_id FROM pets WHERE id=:id", - params, - new JdbcPetRowMapper()); - - List visits = this.jdbcTemplate.query( - "SELECT id as visit_id, visit_date, description FROM visits WHERE pet_id=:id", - params, new JdbcVisitRowMapper()); + JdbcPet pet = this.jdbcClient + .sql("SELECT id, name, birth_date, type_id, owner_id FROM pets WHERE id=:id") + .param("id", petId) + .query(new JdbcPetRowMapper()) + .single(); + + List visits = this.jdbcClient + .sql("SELECT id as visit_id, visit_date, description FROM visits WHERE pet_id=:id") + .param("id", petId) + .query(new JdbcVisitRowMapper()) + .list(); for (Visit visit: visits) { visit.setPet(pet); diff --git a/src/main/resources/spring/business-config.xml b/src/main/resources/spring/business-config.xml index a029c45ab..84244a3d6 100644 --- a/src/main/resources/spring/business-config.xml +++ b/src/main/resources/spring/business-config.xml @@ -68,7 +68,8 @@ - +