View Javadoc
1   package com.randomnoun.common.spring;
2   
3   /* (c) 2013 randomnoun. All Rights Reserved. This work is licensed under a
4    * BSD Simplified License. (http://www.randomnoun.com/bsd-simplified.html)
5    */
6   
7   import java.io.*;
8   import java.sql.*;
9   
10  import org.springframework.dao.TypeMismatchDataAccessException;
11  import org.springframework.jdbc.core.*;
12  
13  import com.randomnoun.common.StreamUtil;
14  
15  
16  
17  /**
18   * This class is intended to replace the standard RowMapper provided by Spring
19   * to return a List of String objects (rather than a List of Maps). The
20   * queries executed by this rowMapper must therefore always evaluate to
21   * a single String or CLOB column (the CLOB will be mapped to a String
22   * if required).
23   *
24   * <p>This class can be used as in the following code fragment:
25   *
26   * <pre style="code">
27                  JdbcTemplate jt = EjbConfig.getEjbConfig().getJdbcTemplate();
28                  List stringList = jt.query(
29                      "SELECT DISTINCT roleName FROM userRole " +
30                      "WHERE customerId = ? ",
31                      new Object[] { new Long(customerId) },
32                      new RowMapperResultReader(new StringRowMapper() ));
33   * </pre>
34   *
35   *
36   * 
37   * @author knoxg
38   */
39  public class StringRowMapper implements RowMapper<String>
40  {
41  
42      /**
43       * Returns a single object representing this row.
44       *
45       * @param resultSet The resultset to map
46       * @param rowNumber The current row number
47       *
48       * @return a single object representing this row.
49       *
50       * @throws TypeMismatchDataAccessException if the first column of the restset is not
51       *   a String or CLOB.
52       */
53      public String mapRow(ResultSet resultSet, int rowNumber)
54          throws SQLException
55      {
56          Object value;
57  
58          value = resultSet.getObject(1);
59  
60          if (value == null) {
61              // just keep it as a null
62          } else if (value.getClass().getName().equals("oracle.sql.CLOB")) {
63          	// need to do text comparison rather than instanceof to get around classloading issues
64              // value = lobHandler.getClobAsString(resultSet, 1);
65          	throw new UnsupportedOperationException("Unexpected CLOB");
66          } else if (value instanceof java.sql.Clob) {
67  			Clob clob = (Clob) value;
68  			ByteArrayOutputStream baos = new ByteArrayOutputStream();
69  			try {
70  				StreamUtil.copyStream(clob.getAsciiStream(), baos, 1024);
71  			} catch (IOException ioe) {
72  				throw (SQLException) new SQLException("IO error transferring CLOB").initCause(ioe);
73  			}
74  			value = baos.toString();
75          } else if (!(value instanceof String)) {
76              throw new TypeMismatchDataAccessException(
77                  "Expecting String/CLOB in column 1 of query (found " +
78                  value.getClass().getName() + ")");
79          }
80  
81          return (String)value;
82      }
83  }