Skip to content
Snippets Groups Projects
Commit 818529b5 authored by Antoine Rey's avatar Antoine Rey
Browse files

#64 Remove N+1 select by using the OneToManyResultSetExtractor of Spring Data Core JDBC Extensions

parent 08d55c97
No related branches found
No related tags found
No related merge requests found
...@@ -18,6 +18,7 @@ ...@@ -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 @@ ...@@ -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 { ...@@ -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> { ...@@ -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));
......
/*
* 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.samples.petclinic.model.Visit;
import java.sql.ResultSet;
import java.sql.SQLException;
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);
}
}
\ No newline at end of file
...@@ -15,17 +15,8 @@ ...@@ -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; ...@@ -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 { ...@@ -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;
} }
} }
/*
* 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;
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;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment