001: /*
002: * Copyright 2002-2005 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.jdbc.core.support;
018:
019: import java.io.IOException;
020: import java.sql.ResultSet;
021: import java.sql.SQLException;
022:
023: import org.springframework.dao.DataAccessException;
024: import org.springframework.dao.EmptyResultDataAccessException;
025: import org.springframework.dao.IncorrectResultSizeDataAccessException;
026: import org.springframework.jdbc.LobRetrievalFailureException;
027: import org.springframework.jdbc.core.ResultSetExtractor;
028:
029: /**
030: * Abstract ResultSetExtractor implementation that assumes streaming of LOB data.
031: * Typically used as inner class, with access to surrounding method arguments.
032: *
033: * <p>Delegates to the <code>streamData</code> template method for streaming LOB
034: * content to some OutputStream, typically using a LobHandler. Converts an
035: * IOException thrown during streaming to a LobRetrievalFailureException.
036: *
037: * <p>A usage example with JdbcTemplate:
038: *
039: * <pre class="code">JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); // reusable object
040: * final LobHandler lobHandler = new DefaultLobHandler(); // reusable object
041: *
042: * jdbcTemplate.query(
043: * "SELECT content FROM imagedb WHERE image_name=?", new Object[] {name},
044: * new AbstractLobStreamingResultSetExtractor() {
045: * public void streamData(ResultSet rs) throws SQLException, IOException {
046: * FileCopyUtils.copy(lobHandler.getBlobAsBinaryStream(rs, 1), contentStream);
047: * }
048: * }
049: * );</pre>
050: *
051: * @author Juergen Hoeller
052: * @since 1.0.2
053: * @see org.springframework.jdbc.support.lob.LobHandler
054: * @see org.springframework.jdbc.LobRetrievalFailureException
055: */
056: public abstract class AbstractLobStreamingResultSetExtractor implements
057: ResultSetExtractor {
058:
059: /**
060: * Delegates to handleNoRowFound, handleMultipleRowsFound and streamData,
061: * according to the ResultSet state. Converts an IOException thrown by
062: * streamData to a LobRetrievalFailureException.
063: * @see #handleNoRowFound
064: * @see #handleMultipleRowsFound
065: * @see #streamData
066: * @see org.springframework.jdbc.LobRetrievalFailureException
067: */
068: public final Object extractData(ResultSet rs) throws SQLException,
069: DataAccessException {
070: if (!rs.next()) {
071: handleNoRowFound();
072: } else {
073: try {
074: streamData(rs);
075: if (rs.next()) {
076: handleMultipleRowsFound();
077: }
078: } catch (IOException ex) {
079: throw new LobRetrievalFailureException(
080: "Couldn't stream LOB content", ex);
081: }
082: }
083: return null;
084: }
085:
086: /**
087: * Handle the case where the ResultSet does not contain a row.
088: * @throws DataAccessException a corresponding exception,
089: * by default an EmptyResultDataAccessException
090: * @see org.springframework.dao.EmptyResultDataAccessException
091: */
092: protected void handleNoRowFound() throws DataAccessException {
093: throw new EmptyResultDataAccessException(
094: "LobStreamingResultSetExtractor did not find row in database",
095: 1);
096: }
097:
098: /**
099: * Handle the case where the ResultSet contains multiple rows.
100: * @throws DataAccessException a corresponding exception,
101: * by default an IncorrectResultSizeDataAccessException
102: * @see org.springframework.dao.IncorrectResultSizeDataAccessException
103: */
104: protected void handleMultipleRowsFound() throws DataAccessException {
105: throw new IncorrectResultSizeDataAccessException(
106: "LobStreamingResultSetExtractor found multiple rows in database",
107: 1);
108: }
109:
110: /**
111: * Stream LOB content from the given ResultSet to some OutputStream.
112: * <p>Typically used as inner class, with access to surrounding method arguments
113: * and to a LobHandler instance variable of the surrounding class.
114: * @param rs the ResultSet to take the LOB content from
115: * @throws SQLException if thrown by JDBC methods
116: * @throws IOException if thrown by stream access methods
117: * @throws DataAccessException in case of custom exceptions
118: * @see org.springframework.jdbc.support.lob.LobHandler#getBlobAsBinaryStream
119: * @see org.springframework.util.FileCopyUtils
120: */
121: protected abstract void streamData(ResultSet rs)
122: throws SQLException, IOException, DataAccessException;
123:
124: }
|