001/* 002 * Copyright 2002-2016 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 * https://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 017package org.springframework.jdbc.support.lob; 018 019import java.io.InputStream; 020import java.io.Reader; 021import java.sql.ResultSet; 022import java.sql.SQLException; 023 024import org.springframework.lang.Nullable; 025 026/** 027 * Abstraction for handling large binary fields and large text fields in 028 * specific databases, no matter if represented as simple types or Large OBjects. 029 * 030 * <p>Provides accessor methods for BLOBs and CLOBs, and acts as factory for 031 * LobCreator instances, to be used as sessions for creating BLOBs or CLOBs. 032 * LobCreators are typically instantiated for each statement execution or for 033 * each transaction; they are not thread-safe because they might track 034 * allocated database resources in order to free them after execution. 035 * 036 * <p>Most databases/drivers should be able to work with {@link DefaultLobHandler}, 037 * which by default delegates to JDBC's direct accessor methods, avoiding the 038 * {@code java.sql.Blob} and {@code java.sql.Clob} API completely. 039 * {@link DefaultLobHandler} can also be configured to access LOBs using 040 * {@code PreparedStatement.setBlob/setClob} (e.g. for PostgreSQL), through 041 * setting the {@link DefaultLobHandler#setWrapAsLob "wrapAsLob"} property. 042 * 043 * <p>Of course, you need to declare different field types for each database. 044 * In Oracle, any binary content needs to go into a BLOB, and all character content 045 * beyond 4000 bytes needs to go into a CLOB. In MySQL, there is no notion of a 046 * CLOB type but rather a LONGTEXT type that behaves like a VARCHAR. For complete 047 * portability, use a LobHandler for fields that might typically require LOBs on 048 * some database because of the field size (take Oracle's numbers as a guideline). 049 * 050 * <p><b>Summarizing the recommended options (for actual LOB fields):</b> 051 * <ul> 052 * <li><b>JDBC 4.0 driver (including Oracle 11g driver):</b> Use {@link DefaultLobHandler}, 053 * potentially with {@code streamAsLob=true} if your database driver requires that 054 * hint when populating a LOB field. Fall back to {@code createTemporaryLob=true} 055 * if you happen to run into LOB size limitations with your (Oracle) database setup. 056 * <li><b>Oracle 10g driver:</b> Use {@link DefaultLobHandler} with standard setup. 057 * On Oracle 10.1, set the "SetBigStringTryClob" connection property; as of Oracle 10.2, 058 * DefaultLobHandler should work with standard setup out of the box. 059 * <li><b>PostgreSQL:</b> Configure {@link DefaultLobHandler} with {@code wrapAsLob=true}, 060 * and use that LobHandler to access OID columns (but not BYTEA) in your database tables. 061 * <li>For all other database drivers (and for non-LOB fields that might potentially 062 * turn into LOBs on some databases): Simply use a plain {@link DefaultLobHandler}. 063 * </ul> 064 * 065 * @author Juergen Hoeller 066 * @since 23.12.2003 067 * @see DefaultLobHandler 068 * @see java.sql.ResultSet#getBlob 069 * @see java.sql.ResultSet#getClob 070 * @see java.sql.ResultSet#getBytes 071 * @see java.sql.ResultSet#getBinaryStream 072 * @see java.sql.ResultSet#getString 073 * @see java.sql.ResultSet#getAsciiStream 074 * @see java.sql.ResultSet#getCharacterStream 075 */ 076public interface LobHandler { 077 078 /** 079 * Retrieve the given column as bytes from the given ResultSet. 080 * Might simply invoke {@code ResultSet.getBytes} or work with 081 * {@code ResultSet.getBlob}, depending on the database and driver. 082 * @param rs the ResultSet to retrieve the content from 083 * @param columnName the column name to use 084 * @return the content as byte array, or {@code null} in case of SQL NULL 085 * @throws SQLException if thrown by JDBC methods 086 * @see java.sql.ResultSet#getBytes 087 */ 088 @Nullable 089 byte[] getBlobAsBytes(ResultSet rs, String columnName) throws SQLException; 090 091 /** 092 * Retrieve the given column as bytes from the given ResultSet. 093 * Might simply invoke {@code ResultSet.getBytes} or work with 094 * {@code ResultSet.getBlob}, depending on the database and driver. 095 * @param rs the ResultSet to retrieve the content from 096 * @param columnIndex the column index to use 097 * @return the content as byte array, or {@code null} in case of SQL NULL 098 * @throws SQLException if thrown by JDBC methods 099 * @see java.sql.ResultSet#getBytes 100 */ 101 @Nullable 102 byte[] getBlobAsBytes(ResultSet rs, int columnIndex) throws SQLException; 103 104 /** 105 * Retrieve the given column as binary stream from the given ResultSet. 106 * Might simply invoke {@code ResultSet.getBinaryStream} or work with 107 * {@code ResultSet.getBlob}, depending on the database and driver. 108 * @param rs the ResultSet to retrieve the content from 109 * @param columnName the column name to use 110 * @return the content as binary stream, or {@code null} in case of SQL NULL 111 * @throws SQLException if thrown by JDBC methods 112 * @see java.sql.ResultSet#getBinaryStream 113 */ 114 @Nullable 115 InputStream getBlobAsBinaryStream(ResultSet rs, String columnName) throws SQLException; 116 117 /** 118 * Retrieve the given column as binary stream from the given ResultSet. 119 * Might simply invoke {@code ResultSet.getBinaryStream} or work with 120 * {@code ResultSet.getBlob}, depending on the database and driver. 121 * @param rs the ResultSet to retrieve the content from 122 * @param columnIndex the column index to use 123 * @return the content as binary stream, or {@code null} in case of SQL NULL 124 * @throws SQLException if thrown by JDBC methods 125 * @see java.sql.ResultSet#getBinaryStream 126 */ 127 @Nullable 128 InputStream getBlobAsBinaryStream(ResultSet rs, int columnIndex) throws SQLException; 129 130 /** 131 * Retrieve the given column as String from the given ResultSet. 132 * Might simply invoke {@code ResultSet.getString} or work with 133 * {@code ResultSet.getClob}, depending on the database and driver. 134 * @param rs the ResultSet to retrieve the content from 135 * @param columnName the column name to use 136 * @return the content as String, or {@code null} in case of SQL NULL 137 * @throws SQLException if thrown by JDBC methods 138 * @see java.sql.ResultSet#getString 139 */ 140 @Nullable 141 String getClobAsString(ResultSet rs, String columnName) throws SQLException; 142 143 /** 144 * Retrieve the given column as String from the given ResultSet. 145 * Might simply invoke {@code ResultSet.getString} or work with 146 * {@code ResultSet.getClob}, depending on the database and driver. 147 * @param rs the ResultSet to retrieve the content from 148 * @param columnIndex the column index to use 149 * @return the content as String, or {@code null} in case of SQL NULL 150 * @throws SQLException if thrown by JDBC methods 151 * @see java.sql.ResultSet#getString 152 */ 153 @Nullable 154 String getClobAsString(ResultSet rs, int columnIndex) throws SQLException; 155 156 /** 157 * Retrieve the given column as ASCII stream from the given ResultSet. 158 * Might simply invoke {@code ResultSet.getAsciiStream} or work with 159 * {@code ResultSet.getClob}, depending on the database and driver. 160 * @param rs the ResultSet to retrieve the content from 161 * @param columnName the column name to use 162 * @return the content as ASCII stream, or {@code null} in case of SQL NULL 163 * @throws SQLException if thrown by JDBC methods 164 * @see java.sql.ResultSet#getAsciiStream 165 */ 166 @Nullable 167 InputStream getClobAsAsciiStream(ResultSet rs, String columnName) throws SQLException; 168 169 /** 170 * Retrieve the given column as ASCII stream from the given ResultSet. 171 * Might simply invoke {@code ResultSet.getAsciiStream} or work with 172 * {@code ResultSet.getClob}, depending on the database and driver. 173 * @param rs the ResultSet to retrieve the content from 174 * @param columnIndex the column index to use 175 * @return the content as ASCII stream, or {@code null} in case of SQL NULL 176 * @throws SQLException if thrown by JDBC methods 177 * @see java.sql.ResultSet#getAsciiStream 178 */ 179 @Nullable 180 InputStream getClobAsAsciiStream(ResultSet rs, int columnIndex) throws SQLException; 181 182 /** 183 * Retrieve the given column as character stream from the given ResultSet. 184 * Might simply invoke {@code ResultSet.getCharacterStream} or work with 185 * {@code ResultSet.getClob}, depending on the database and driver. 186 * @param rs the ResultSet to retrieve the content from 187 * @param columnName the column name to use 188 * @return the content as character stream 189 * @throws SQLException if thrown by JDBC methods 190 * @see java.sql.ResultSet#getCharacterStream 191 */ 192 Reader getClobAsCharacterStream(ResultSet rs, String columnName) throws SQLException; 193 194 /** 195 * Retrieve the given column as character stream from the given ResultSet. 196 * Might simply invoke {@code ResultSet.getCharacterStream} or work with 197 * {@code ResultSet.getClob}, depending on the database and driver. 198 * @param rs the ResultSet to retrieve the content from 199 * @param columnIndex the column index to use 200 * @return the content as character stream 201 * @throws SQLException if thrown by JDBC methods 202 * @see java.sql.ResultSet#getCharacterStream 203 */ 204 Reader getClobAsCharacterStream(ResultSet rs, int columnIndex) throws SQLException; 205 206 /** 207 * Create a new {@link LobCreator} instance, i.e. a session for creating BLOBs 208 * and CLOBs. Needs to be closed after the created LOBs are not needed anymore - 209 * typically after statement execution or transaction completion. 210 * @return the new LobCreator instance 211 * @see LobCreator#close() 212 */ 213 LobCreator getLobCreator(); 214 215}