1. /*
  2. * Copyright 2002-2004 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.springframework.jdbc.core;
  17. import java.sql.ResultSet;
  18. import java.sql.SQLException;
  19. import java.util.ArrayList;
  20. import java.util.LinkedList;
  21. import java.util.List;
  22. /**
  23. * Adapter implementation of the ResultReader interface that delegates to
  24. * a RowMapper which is supposed to create an object for each row.
  25. * Each object is added to the results list of this ResultReader.
  26. *
  27. * <p>Useful for the typical case of one object per row in the database table.
  28. * The number of entries in the results list will match the number of rows.
  29. *
  30. * <p>Note that a RowMapper object is typically stateless and thus reusable;
  31. * just the RowMapperResultReader adapter is stateful.
  32. *
  33. * <p>A usage example with JdbcTemplate:
  34. *
  35. * <pre>
  36. * JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); // reusable object
  37. * RowMapper rowMapper = new UserRowMapper(); // reusable object
  38. *
  39. * List allUsers = jdbcTemplate.query("select * from user", new RowMapperResultReader(rowMapper, 10));
  40. *
  41. * List userResults = jdbcTemplate.query("select * from user where id=?", new Object[] {id},
  42. * new RowMapperResultReader(rowMapper, 1));
  43. * User user = (User) DataAccessUtils.uniqueResult(userResults);</pre>
  44. *
  45. * <p>Alternatively, consider subclassing MappingSqlQuery from the jdbc.object
  46. * package: Instead of working with separate JdbcTemplate and RowMapper objects,
  47. * you can have executable query objects (containing row-mapping logic) there.
  48. *
  49. * @author Juergen Hoeller
  50. * @since 25.05.2004
  51. * @see RowMapper
  52. * @see org.springframework.dao.support.DataAccessUtils#uniqueResult
  53. * @see org.springframework.jdbc.object.MappingSqlQuery
  54. */
  55. public class RowMapperResultReader implements ResultReader {
  56. /** List to save results in */
  57. private final List results;
  58. /** The RowMapper implementation that will be used to map rows */
  59. private final RowMapper rowMapper;
  60. /** The counter used to count rows */
  61. private int rowNum = 0;
  62. /**
  63. * Create a new RowMapperResultReader.
  64. * @param rowMapper the RowMapper which creates an object for each row
  65. */
  66. public RowMapperResultReader(RowMapper rowMapper) {
  67. this(rowMapper, 0);
  68. }
  69. /**
  70. * Create a new RowMapperResultReader.
  71. * @param rowMapper the RowMapper which creates an object for each row
  72. * @param rowsExpected the number of expected rows
  73. * (just used for optimized collection handling)
  74. */
  75. public RowMapperResultReader(RowMapper rowMapper, int rowsExpected) {
  76. // Use the more efficient collection if we know how many rows to expect:
  77. // ArrayList in case of a known row count, LinkedList if unknown
  78. this.results = (rowsExpected > 0) ? (List) new ArrayList(rowsExpected) : (List) new LinkedList();
  79. this.rowMapper = rowMapper;
  80. }
  81. public void processRow(ResultSet rs) throws SQLException {
  82. this.results.add(this.rowMapper.mapRow(rs, this.rowNum++));
  83. }
  84. public List getResults() {
  85. return this.results;
  86. }
  87. }