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.ResultSetMetaData;
  19. import java.sql.SQLException;
  20. /**
  21. * Implementation of RowCallbackHandler. Convenient superclass for callback handlers.
  22. * An instance can only be used once.
  23. *
  24. * <p>We can either use this on its own (for example, in a test case, to ensure
  25. * that our result sets have valid dimensions), or use it as a superclass
  26. * for callback handlers that actually do something, and will benefit
  27. * from the dimension information it provides.
  28. *
  29. * <p>A usage example with JdbcTemplate:
  30. *
  31. * <pre>
  32. * JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); // reusable object
  33. *
  34. * RowCountCallbackHandler countCallback = new RowCountCallbackHandler(); // not reusable
  35. * jdbcTemplate.query("select * from user", countCallback);
  36. * int rowCount = countCallback.getRowCount();</pre>
  37. *
  38. * @author Rod Johnson
  39. * @since May 3, 2001
  40. * @version $Id: RowCountCallbackHandler.java,v 1.4 2004/05/26 10:11:21 jhoeller Exp $
  41. */
  42. public class RowCountCallbackHandler implements RowCallbackHandler {
  43. /** Rows we've seen so far */
  44. private int rowCount;
  45. /** Columns we've seen so far */
  46. private int columnCount;
  47. /**
  48. * Indexed from 0. Type (as in java.sql.Types) for the columns
  49. * as returned by ResultSetMetaData object.
  50. */
  51. private int[] columnTypes;
  52. private String[] columnNames;
  53. /**
  54. * Implementation of ResultSetCallbackHandler.
  55. * Work out column size if this is the first row,* otherwise just count rows.
  56. * <p>Subclasses can perform custom extraction or processing
  57. * by overriding the processRow(ResultSet, int) method.
  58. */
  59. public final void processRow(ResultSet rs) throws SQLException {
  60. if (this.rowCount == 0) {
  61. ResultSetMetaData rsmd = rs.getMetaData();
  62. this.columnCount = rsmd.getColumnCount();
  63. this.columnTypes = new int[this.columnCount];
  64. this.columnNames = new String[this.columnCount];
  65. for (int i = 0; i < this.columnCount; i++) {
  66. this.columnTypes[i] = rsmd.getColumnType(i + 1);
  67. this.columnNames[i] = rsmd.getColumnName(i + 1);
  68. }
  69. // could also get column names
  70. }
  71. processRow(rs, this.rowCount++);
  72. }
  73. /**
  74. * Subclasses may override this to perform custom extraction
  75. * or processing. This class's implementation does nothing.
  76. * @param rs ResultSet to extract data from. This method is
  77. * invoked for each row
  78. * @param rowNum number of the current row (starting from 0)
  79. */
  80. protected void processRow(ResultSet rs, int rowNum) throws SQLException {
  81. }
  82. /**
  83. * Return the types of the columns as java.sql.Types constants
  84. * Valid after processRow is invoked the first time.
  85. * @return the types of the columns as java.sql.Types constants.
  86. * <b>Indexed from 0 to n-1.</b>
  87. */
  88. public final int[] getColumnTypes() {
  89. return columnTypes;
  90. }
  91. /**
  92. * Return the names of the columns.
  93. * Valid after processRow is invoked the first time.
  94. * @return the names of the columns.
  95. * <b>Indexed from 0 to n-1.</b>
  96. */
  97. public final String[] getColumnNames() {
  98. return columnNames;
  99. }
  100. /**
  101. * Return the row count of this ResultSet
  102. * Only valid after processing is complete
  103. * @return the number of rows in this ResultSet
  104. */
  105. public final int getRowCount() {
  106. return rowCount;
  107. }
  108. /**
  109. * Return the number of columns in this result set.
  110. * Valid once we've seen the first row,
  111. * so subclasses can use it during processing
  112. * @return the number of columns in this result set
  113. */
  114. public final int getColumnCount() {
  115. return columnCount;
  116. }
  117. }