001package com.randomnoun.common.spring; 002 003/* (c) 2013 randomnoun. All Rights Reserved. This work is licensed under a 004 * BSD Simplified License. (http://www.randomnoun.com/bsd-simplified.html) 005 */ 006 007import java.io.*; 008import java.sql.*; 009 010import org.springframework.dao.TypeMismatchDataAccessException; 011import org.springframework.jdbc.core.*; 012 013import com.randomnoun.common.StreamUtil; 014 015 016 017/** 018 * This class is intended to replace the standard RowMapper provided by Spring 019 * to return a List of String objects (rather than a List of Maps). The 020 * queries executed by this rowMapper must therefore always evaluate to 021 * a single String or CLOB column (the CLOB will be mapped to a String 022 * if required). 023 * 024 * <p>This class can be used as in the following code fragment: 025 * 026 * <pre style="code"> 027 JdbcTemplate jt = EjbConfig.getEjbConfig().getJdbcTemplate(); 028 List stringList = jt.query( 029 "SELECT DISTINCT roleName FROM userRole " + 030 "WHERE customerId = ? ", 031 new Object[] { new Long(customerId) }, 032 new RowMapperResultReader(new StringRowMapper() )); 033 * </pre> 034 * 035 * 036 * 037 * @author knoxg 038 */ 039public class StringRowMapper implements RowMapper<String> 040{ 041 042 /** 043 * Returns a single object representing this row. 044 * 045 * @param resultSet The resultset to map 046 * @param rowNumber The current row number 047 * 048 * @return a single object representing this row. 049 * 050 * @throws TypeMismatchDataAccessException if the first column of the restset is not 051 * a String or CLOB. 052 */ 053 public String mapRow(ResultSet resultSet, int rowNumber) 054 throws SQLException 055 { 056 Object value; 057 058 value = resultSet.getObject(1); 059 060 if (value == null) { 061 // just keep it as a null 062 } else if (value.getClass().getName().equals("oracle.sql.CLOB")) { 063 // need to do text comparison rather than instanceof to get around classloading issues 064 // value = lobHandler.getClobAsString(resultSet, 1); 065 throw new UnsupportedOperationException("Unexpected CLOB"); 066 } else if (value instanceof java.sql.Clob) { 067 Clob clob = (Clob) value; 068 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 069 try { 070 StreamUtil.copyStream(clob.getAsciiStream(), baos, 1024); 071 } catch (IOException ioe) { 072 throw (SQLException) new SQLException("IO error transferring CLOB").initCause(ioe); 073 } 074 value = baos.toString(); 075 } else if (!(value instanceof String)) { 076 throw new TypeMismatchDataAccessException( 077 "Expecting String/CLOB in column 1 of query (found " + 078 value.getClass().getName() + ")"); 079 } 080 081 return (String)value; 082 } 083}