mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-07-15 20:35:49 +00:00
Merge pull request #82 from arey/#64-optim1
#64 Optimize N+1 select by using the OneToManyResultSetExtractor
This commit is contained in:
commit
8965499757
6 changed files with 119 additions and 33 deletions
14
pom.xml
14
pom.xml
|
@ -18,6 +18,7 @@
|
||||||
<!-- Spring -->
|
<!-- Spring -->
|
||||||
<spring-framework.version>4.1.6.RELEASE</spring-framework.version>
|
<spring-framework.version>4.1.6.RELEASE</spring-framework.version>
|
||||||
<spring-data-jpa.version>1.8.0.RELEASE</spring-data-jpa.version>
|
<spring-data-jpa.version>1.8.0.RELEASE</spring-data-jpa.version>
|
||||||
|
<spring-data-jdbc.version>1.1.0.RELEASE</spring-data-jdbc.version>
|
||||||
|
|
||||||
|
|
||||||
<!-- Java EE / Java SE dependencies -->
|
<!-- Java EE / Java SE dependencies -->
|
||||||
|
@ -127,6 +128,19 @@
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.data</groupId>
|
||||||
|
<artifactId>spring-data-jdbc-core</artifactId>
|
||||||
|
<version>${spring-data-jdbc.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>*</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<!-- because Spring Data usually comes with a slightly older version of Spring -->
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-jdbc</artifactId>
|
<artifactId>spring-jdbc</artifactId>
|
||||||
|
|
|
@ -116,18 +116,12 @@ public class JdbcOwnerRepositoryImpl implements OwnerRepository {
|
||||||
Map<String, Object> params = new HashMap<String, Object>();
|
Map<String, Object> params = new HashMap<String, Object>();
|
||||||
params.put("id", owner.getId().intValue());
|
params.put("id", owner.getId().intValue());
|
||||||
final List<JdbcPet> pets = this.namedParameterJdbcTemplate.query(
|
final List<JdbcPet> pets = this.namedParameterJdbcTemplate.query(
|
||||||
"SELECT id, name, birth_date, type_id, owner_id FROM pets WHERE owner_id=:id",
|
"SELECT pets.id, name, birth_date, type_id, owner_id, visits.id, visit_date, description, pet_id FROM pets LEFT OUTER JOIN visits ON pets.id = pet_id WHERE owner_id=:id",
|
||||||
params,
|
params,
|
||||||
new JdbcPetRowMapper()
|
new JdbcPetVisitExtractor()
|
||||||
);
|
);
|
||||||
for (JdbcPet pet : pets) {
|
for (JdbcPet pet : pets) {
|
||||||
owner.addPet(pet);
|
owner.addPet(pet);
|
||||||
// Pet types have not been loaded at this stage. They are loaded separately
|
|
||||||
pet.setType(EntityUtils.getById(getPetTypes(), PetType.class, pet.getTypeId()));
|
|
||||||
List<Visit> visits = this.visitRepository.findByPetId(pet.getId());
|
|
||||||
for (Visit visit : visits) {
|
|
||||||
pet.addVisit(visit);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ class JdbcPetRowMapper extends BeanPropertyRowMapper<JdbcPet> {
|
||||||
@Override
|
@Override
|
||||||
public JdbcPet mapRow(ResultSet rs, int rownum) throws SQLException {
|
public JdbcPet mapRow(ResultSet rs, int rownum) throws SQLException {
|
||||||
JdbcPet pet = new JdbcPet();
|
JdbcPet pet = new JdbcPet();
|
||||||
pet.setId(rs.getInt("id"));
|
pet.setId(rs.getInt("pets.id"));
|
||||||
pet.setName(rs.getString("name"));
|
pet.setName(rs.getString("name"));
|
||||||
Date birthDate = rs.getDate("birth_date");
|
Date birthDate = rs.getDate("birth_date");
|
||||||
pet.setBirthDate(new DateTime(birthDate));
|
pet.setBirthDate(new DateTime(birthDate));
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2015 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.samples.petclinic.repository.jdbc;
|
||||||
|
|
||||||
|
import org.springframework.data.jdbc.core.OneToManyResultSetExtractor;
|
||||||
|
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||||
|
import org.springframework.samples.petclinic.model.Visit;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ResultSetExtractor} implementation by using the
|
||||||
|
* {@link OneToManyResultSetExtractor} of Spring Data Core JDBC Extensions.
|
||||||
|
*/
|
||||||
|
public class JdbcPetVisitExtractor extends
|
||||||
|
OneToManyResultSetExtractor<JdbcPet, Visit, Integer> {
|
||||||
|
|
||||||
|
public JdbcPetVisitExtractor() {
|
||||||
|
super(new JdbcPetRowMapper(), new JdbcVisitRowMapper());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Integer mapPrimaryKey(ResultSet rs) throws SQLException {
|
||||||
|
return rs.getInt("pets.id");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Integer mapForeignKey(ResultSet rs) throws SQLException {
|
||||||
|
if (rs.getObject("visits.pet_id") == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return rs.getInt("visits.pet_id");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addChild(JdbcPet root, Visit child) {
|
||||||
|
root.addVisit(child);
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,17 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.samples.petclinic.repository.jdbc;
|
package org.springframework.samples.petclinic.repository.jdbc;
|
||||||
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
|
|
||||||
import org.joda.time.DateTime;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||||
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
|
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
|
||||||
|
@ -33,6 +24,9 @@ import org.springframework.samples.petclinic.model.Visit;
|
||||||
import org.springframework.samples.petclinic.repository.VisitRepository;
|
import org.springframework.samples.petclinic.repository.VisitRepository;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple JDBC-based implementation of the {@link VisitRepository} interface.
|
* A simple JDBC-based implementation of the {@link VisitRepository} interface.
|
||||||
*
|
*
|
||||||
|
@ -90,21 +84,9 @@ public class JdbcVisitRepositoryImpl implements VisitRepository {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Visit> findByPetId(Integer petId) {
|
public List<Visit> findByPetId(Integer petId) {
|
||||||
final List<Visit> visits = this.jdbcTemplate.query(
|
return this.jdbcTemplate.query(
|
||||||
"SELECT id, visit_date, description FROM visits WHERE pet_id=?",
|
"SELECT id as visit_id, visit_date, description FROM visits WHERE pet_id=?",
|
||||||
new BeanPropertyRowMapper<Visit>() {
|
new JdbcVisitRowMapper(), petId);
|
||||||
@Override
|
|
||||||
public Visit mapRow(ResultSet rs, int row) throws SQLException {
|
|
||||||
Visit visit = new Visit();
|
|
||||||
visit.setId(rs.getInt("id"));
|
|
||||||
Date visitDate = rs.getDate("visit_date");
|
|
||||||
visit.setDate(new DateTime(visitDate));
|
|
||||||
visit.setDescription(rs.getString("description"));
|
|
||||||
return visit;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
petId);
|
|
||||||
return visits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2015 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.samples.petclinic.repository.jdbc;
|
||||||
|
|
||||||
|
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
|
import org.springframework.samples.petclinic.model.Visit;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link RowMapper} implementation mapping data from a {@link ResultSet} to the corresponding properties
|
||||||
|
* of the {@link Visit} class.
|
||||||
|
*/
|
||||||
|
class JdbcVisitRowMapper implements RowMapper<Visit> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Visit mapRow(ResultSet rs, int row) throws SQLException {
|
||||||
|
Visit visit = new Visit();
|
||||||
|
visit.setId(rs.getInt("visits.id"));
|
||||||
|
Date visitDate = rs.getDate("visit_date");
|
||||||
|
visit.setDate(new DateTime(visitDate));
|
||||||
|
visit.setDescription(rs.getString("description"));
|
||||||
|
return visit;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue