KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > orm > ibatis > support > AbstractLobTypeHandler


1 /*
2  * Copyright 2002-2005 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.orm.ibatis.support;
18
19 import java.io.IOException JavaDoc;
20 import java.sql.CallableStatement JavaDoc;
21 import java.sql.PreparedStatement JavaDoc;
22 import java.sql.ResultSet JavaDoc;
23 import java.sql.SQLException JavaDoc;
24
25 import com.ibatis.sqlmap.engine.type.BaseTypeHandler;
26
27 import org.springframework.jdbc.datasource.DataSourceUtils;
28 import org.springframework.jdbc.support.lob.LobCreator;
29 import org.springframework.jdbc.support.lob.LobHandler;
30 import org.springframework.orm.ibatis.SqlMapClientFactoryBean;
31 import org.springframework.transaction.support.TransactionSynchronizationAdapter;
32 import org.springframework.transaction.support.TransactionSynchronizationManager;
33
34 /**
35  * Abstract base class for iBATIS TypeHandler implementations that map to LOBs.
36  * Retrieves the LobHandler to use from SqlMapClientFactoryBean at config time.
37  *
38  * <p>For writing LOBs, an active Spring transaction synchronization is required,
39  * to be able to register a synchronization that closes the LobCreator.
40  *
41  * <p>Offers template methods for setting parameters and getting result values,
42  * passing in the LobHandler or LobCreator to use.
43  *
44  * @author Juergen Hoeller
45  * @since 1.1.5
46  * @see org.springframework.jdbc.support.lob.LobHandler
47  * @see org.springframework.jdbc.support.lob.LobCreator
48  * @see org.springframework.orm.ibatis.SqlMapClientFactoryBean#setLobHandler
49  */

50 public abstract class AbstractLobTypeHandler extends BaseTypeHandler {
51
52     /**
53      * Order value for TransactionSynchronization objects that clean up LobCreators.
54      * Return DataSourceUtils.#CONNECTION_SYNCHRONIZATION_ORDER - 100 to execute
55      * LobCreator cleanup before JDBC Connection cleanup, if any.
56      * @see org.springframework.jdbc.datasource.DataSourceUtils#CONNECTION_SYNCHRONIZATION_ORDER
57      */

58     public static final int LOB_CREATOR_SYNCHRONIZATION_ORDER =
59             DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 200;
60
61     private LobHandler lobHandler;
62
63
64     /**
65      * Constructor used by iBATIS: fetches config-time LobHandler from
66      * SqlMapClientFactoryBean.
67      * @see org.springframework.orm.ibatis.SqlMapClientFactoryBean#getConfigTimeLobHandler
68      */

69     public AbstractLobTypeHandler() {
70         this(SqlMapClientFactoryBean.getConfigTimeLobHandler());
71     }
72
73     /**
74      * Constructor used for testing: takes an explicit LobHandler.
75      */

76     protected AbstractLobTypeHandler(LobHandler lobHandler) {
77         if (lobHandler == null) {
78             throw new IllegalStateException JavaDoc("No LobHandler found for configuration - " +
79                 "lobHandler property must be set on SqlMapClientFactoryBean");
80         }
81         this.lobHandler = lobHandler;
82     }
83
84
85     /**
86      * This implementation delegates to setParameterInternal,
87      * passing in a transaction-synchronized LobCreator for the
88      * LobHandler of this type.
89      * @see #setParameterInternal
90      */

91     public final void setParameter(PreparedStatement JavaDoc ps, int i, Object JavaDoc parameter, String JavaDoc jdbcType)
92             throws SQLException JavaDoc {
93
94         if (!TransactionSynchronizationManager.isSynchronizationActive()) {
95             throw new IllegalStateException JavaDoc("Spring transaction synchronization needs to be active for " +
96                     "setting values in iBATIS TypeHandlers that delegate to a Spring LobHandler");
97         }
98         final LobCreator lobCreator = this.lobHandler.getLobCreator();
99         try {
100             setParameterInternal(ps, i, parameter, jdbcType, lobCreator);
101         }
102         catch (IOException JavaDoc ex) {
103             throw new SQLException JavaDoc("I/O errors during LOB access: " + ex.getMessage());
104         }
105
106         TransactionSynchronizationManager.registerSynchronization(
107                 new LobCreatorSynchronization(lobCreator));
108     }
109
110     /**
111      * This implementation delegates to the getResult version
112      * that takes a column index.
113      * @see #getResult(java.sql.ResultSet, String)
114      * @see java.sql.ResultSet#findColumn
115      */

116     public final Object JavaDoc getResult(ResultSet JavaDoc rs, String JavaDoc columnName) throws SQLException JavaDoc {
117         return getResult(rs, rs.findColumn(columnName));
118     }
119
120     /**
121      * This implementation delegates to getResultInternal,
122      * passing in the LobHandler of this type.
123      * @see #getResultInternal
124      */

125     public final Object JavaDoc getResult(ResultSet JavaDoc rs, int columnIndex) throws SQLException JavaDoc {
126         try {
127             return getResultInternal(rs, columnIndex, this.lobHandler);
128         }
129         catch (IOException JavaDoc ex) {
130             throw new SQLException JavaDoc(
131                     "I/O errors during LOB access: " + ex.getClass().getName() + ": " + ex.getMessage());
132         }
133     }
134
135     /**
136      * This implementation always throws a SQLException:
137      * retrieving LOBs from a CallableStatement is not supported.
138      */

139     public Object JavaDoc getResult(CallableStatement JavaDoc cs, int columnIndex) throws SQLException JavaDoc {
140         throw new SQLException JavaDoc("Retrieving LOBs from a CallableStatement is not supported");
141     }
142
143
144     /**
145      * Template method to set the given value on the given statement.
146      * @param ps the PreparedStatement to set on
147      * @param index the statement parameter index
148      * @param value the parameter value to set
149      * @param jdbcType the JDBC type of the parameter
150      * @param lobCreator the LobCreator to use
151      * @throws SQLException if thrown by JDBC methods
152      * @throws IOException if thrown by streaming methods
153      */

154     protected abstract void setParameterInternal(
155             PreparedStatement JavaDoc ps, int index, Object JavaDoc value, String JavaDoc jdbcType, LobCreator lobCreator)
156             throws SQLException JavaDoc, IOException JavaDoc;
157
158     /**
159      * Template method to extract a value from the given result set.
160      * @param rs the ResultSet to extract from
161      * @param index the index in the ResultSet
162      * @param lobHandler the LobHandler to use
163      * @return the extracted value
164      * @throws SQLException if thrown by JDBC methods
165      * @throws IOException if thrown by streaming methods
166      */

167     protected abstract Object JavaDoc getResultInternal(ResultSet JavaDoc rs, int index, LobHandler lobHandler)
168             throws SQLException JavaDoc, IOException JavaDoc;
169
170
171     /**
172      * Callback for resource cleanup at the end of a Spring transaction.
173      * Invokes LobCreator.close to clean up temporary LOBs that might have been created.
174      * @see org.springframework.jdbc.support.lob.LobCreator#close
175      */

176     private static class LobCreatorSynchronization extends TransactionSynchronizationAdapter {
177
178         private final LobCreator lobCreator;
179
180         public LobCreatorSynchronization(LobCreator lobCreator) {
181             this.lobCreator = lobCreator;
182         }
183
184         public int getOrder() {
185             return LOB_CREATOR_SYNCHRONIZATION_ORDER;
186         }
187
188         public void beforeCompletion() {
189             this.lobCreator.close();
190         }
191     }
192
193 }
194
Popular Tags