001: /*
002: * Copyright 2002-2006 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.InputStream;
020: import java.io.Reader;
021: import java.sql.PreparedStatement;
022: import java.sql.SQLException;
023: import java.sql.Types;
024:
025: import org.springframework.jdbc.core.DisposableSqlTypeValue;
026: import org.springframework.jdbc.support.lob.DefaultLobHandler;
027: import org.springframework.jdbc.support.lob.LobCreator;
028: import org.springframework.jdbc.support.lob.LobHandler;
029:
030: /**
031: * Object to represent an SQL BLOB/CLOB value parameter. BLOBs can either be an
032: * InputStream or a byte array. CLOBs can be in the form of a Reader, InputStream
033: * or String. Each CLOB/BLOB value will be stored together with its length.
034: * The type is based on which constructor is used. Objects of this class are
035: * immutable except for the LobCreator reference. Use them and discard them.
036: *
037: * <p>This class holds a reference to a LocCreator that must be closed after the
038: * update has completed. This is done via a call to the closeLobCreator method.
039: * All handling of the LobCreator is done by the framework classes that use it -
040: * no need to set or close the LobCreator for end users of this class.
041: *
042: * <p>A usage example:
043: *
044: * <pre class="code">JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); // reusable object
045: * LobHandler lobHandler = new DefaultLobHandler(); // reusable object
046: *
047: * jdbcTemplate.update(
048: * "INSERT INTO imagedb (image_name, content, description) VALUES (?, ?, ?)",
049: * new Object[] {
050: * name,
051: * new SqlLobValue(contentStream, contentLength, lobHandler),
052: * new SqlLobValue(description, lobHandler)
053: * },
054: * new int[] {Types.VARCHAR, Types.BLOB, Types.CLOB});
055: * </pre>
056: *
057: * @author Thomas Risberg
058: * @author Juergen Hoeller
059: * @since 1.1
060: * @see org.springframework.jdbc.support.lob.LobHandler
061: * @see org.springframework.jdbc.support.lob.LobCreator
062: * @see org.springframework.jdbc.core.JdbcTemplate#update(String, Object[], int[])
063: * @see org.springframework.jdbc.object.SqlUpdate#update(Object[])
064: * @see org.springframework.jdbc.object.StoredProcedure#execute(java.util.Map)
065: */
066: public class SqlLobValue implements DisposableSqlTypeValue {
067:
068: private final Object content;
069:
070: private final int length;
071:
072: /**
073: * This contains a reference to the LobCreator - so we can close it
074: * once the update is done.
075: */
076: private final LobCreator lobCreator;
077:
078: /**
079: * Create a new BLOB value with the given byte array,
080: * using a DefaultLobHandler.
081: * @param bytes the byte array containing the BLOB value
082: * @see org.springframework.jdbc.support.lob.DefaultLobHandler
083: */
084: public SqlLobValue(byte[] bytes) {
085: this (bytes, new DefaultLobHandler());
086: }
087:
088: /**
089: * Create a new BLOB value with the given byte array.
090: * @param bytes the byte array containing the BLOB value
091: * @param lobHandler the LobHandler to be used
092: */
093: public SqlLobValue(byte[] bytes, LobHandler lobHandler) {
094: this .content = bytes;
095: this .length = (bytes != null ? bytes.length : 0);
096: this .lobCreator = lobHandler.getLobCreator();
097: }
098:
099: /**
100: * Create a new CLOB value with the given content string,
101: * using a DefaultLobHandler.
102: * @param content the String containing the CLOB value
103: * @see org.springframework.jdbc.support.lob.DefaultLobHandler
104: */
105: public SqlLobValue(String content) {
106: this (content, new DefaultLobHandler());
107: }
108:
109: /**
110: * Create a new CLOB value with the given content string.
111: * @param content the String containing the CLOB value
112: * @param lobHandler the LobHandler to be used
113: */
114: public SqlLobValue(String content, LobHandler lobHandler) {
115: this .content = content;
116: this .length = (content != null ? content.length() : 0);
117: this .lobCreator = lobHandler.getLobCreator();
118: }
119:
120: /**
121: * Create a new BLOB/CLOB value with the given stream,
122: * using a DefaultLobHandler.
123: * @param stream the stream containing the LOB value
124: * @param length the length of the LOB value
125: * @see org.springframework.jdbc.support.lob.DefaultLobHandler
126: */
127: public SqlLobValue(InputStream stream, int length) {
128: this (stream, length, new DefaultLobHandler());
129: }
130:
131: /**
132: * Create a new BLOB/CLOB value with the given stream.
133: * @param stream the stream containing the LOB value
134: * @param length the length of the LOB value
135: * @param lobHandler the LobHandler to be used
136: */
137: public SqlLobValue(InputStream stream, int length,
138: LobHandler lobHandler) {
139: this .content = stream;
140: this .length = length;
141: this .lobCreator = lobHandler.getLobCreator();
142: }
143:
144: /**
145: * Create a new CLOB value with the given character stream,
146: * using a DefaultLobHandler.
147: * @param reader the character stream containing the CLOB value
148: * @param length the length of the CLOB value
149: * @see org.springframework.jdbc.support.lob.DefaultLobHandler
150: */
151: public SqlLobValue(Reader reader, int length) {
152: this (reader, length, new DefaultLobHandler());
153: }
154:
155: /**
156: * Create a new CLOB value with the given character stream.
157: * @param reader the character stream containing the CLOB value
158: * @param length the length of the CLOB value
159: * @param lobHandler the LobHandler to be used
160: */
161: public SqlLobValue(Reader reader, int length, LobHandler lobHandler) {
162: this .content = reader;
163: this .length = length;
164: this .lobCreator = lobHandler.getLobCreator();
165: }
166:
167: /**
168: * Set the specified content via the LobCreator.
169: */
170: public void setTypeValue(PreparedStatement ps, int paramIndex,
171: int sqlType, String typeName) throws SQLException {
172: if (sqlType == Types.BLOB) {
173: if (this .content instanceof byte[] || this .content == null) {
174: this .lobCreator.setBlobAsBytes(ps, paramIndex,
175: (byte[]) this .content);
176: } else if (this .content instanceof String) {
177: this .lobCreator.setBlobAsBytes(ps, paramIndex,
178: ((String) this .content).getBytes());
179: } else if (this .content instanceof InputStream) {
180: this .lobCreator.setBlobAsBinaryStream(ps, paramIndex,
181: (InputStream) this .content, this .length);
182: } else {
183: throw new IllegalArgumentException("Content type ["
184: + this .content.getClass().getName()
185: + "] not supported for BLOB columns");
186: }
187: } else if (sqlType == Types.CLOB) {
188: if (this .content instanceof String || this .content == null) {
189: this .lobCreator.setClobAsString(ps, paramIndex,
190: (String) this .content);
191: } else if (this .content instanceof InputStream) {
192: this .lobCreator.setClobAsAsciiStream(ps, paramIndex,
193: (InputStream) this .content, this .length);
194: } else if (this .content instanceof Reader) {
195: this .lobCreator.setClobAsCharacterStream(ps,
196: paramIndex, (Reader) this .content, this .length);
197: } else {
198: throw new IllegalArgumentException("Content type ["
199: + this .content.getClass().getName()
200: + "] not supported for CLOB columns");
201: }
202: } else {
203: throw new IllegalArgumentException(
204: "SqlLobValue only supports SQL types BLOB and CLOB");
205: }
206: }
207:
208: /**
209: * Close the LobCreator, if any.
210: */
211: public void cleanup() {
212: this.lobCreator.close();
213: }
214:
215: }
|