1. /*
  2. * Copyright 2002-2004 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. package org.springframework.orm.ibatis;
  17. import java.sql.Connection;
  18. import java.sql.SQLException;
  19. import java.util.List;
  20. import java.util.Map;
  21. import javax.sql.DataSource;
  22. import com.ibatis.db.sqlmap.MappedStatement;
  23. import com.ibatis.db.sqlmap.RowHandler;
  24. import com.ibatis.db.sqlmap.SqlMap;
  25. import org.springframework.dao.DataAccessException;
  26. import org.springframework.jdbc.datasource.DataSourceUtils;
  27. import org.springframework.jdbc.support.JdbcAccessor;
  28. /**
  29. * Helper class that simplifies data access via the MappedStatement API of the
  30. * iBATIS Database Layer, and converts checked SQLExceptions into unchecked
  31. * DataAccessExceptions, compatible to the org.springframework.dao exception
  32. * hierarchy. Uses the same SQLExceptionTranslator mechanism as JdbcTemplate.
  33. *
  34. * <p>The main method is execute, taking the name of a mapped statement defined
  35. * in the iBATIS SqlMap config file and a callback that implements a data access
  36. * action on the specified statement.
  37. *
  38. * <p>This class provides numerous convenience methods that mirror MappedStatement's
  39. * executeXXX methods. See the MappedStatement javadocs for details on those methods.
  40. *
  41. * <p>NOTE: The SqlMap/MappedStatement API is the one to use with iBATIS SQL Maps 1.x.
  42. * The SqlMapClient/SqlMapSession API is only available with SQL Maps 2.
  43. *
  44. * @author Juergen Hoeller
  45. * @since 28.11.2003
  46. * @see #execute
  47. * @see #setSqlMap
  48. * @see #setDataSource
  49. * @see #setExceptionTranslator
  50. * @see com.ibatis.db.sqlmap.MappedStatement
  51. */
  52. public class SqlMapTemplate extends JdbcAccessor implements SqlMapOperations {
  53. private SqlMap sqlMap;
  54. /**
  55. * Create a new SqlMapTemplate.
  56. */
  57. public SqlMapTemplate() {
  58. }
  59. /**
  60. * Create a new SqlMapTemplate.
  61. * @param dataSource JDBC DataSource to obtain connections from
  62. * @param sqlMap iBATIS SqlMap that defines the mapped statements
  63. */
  64. public SqlMapTemplate(DataSource dataSource, SqlMap sqlMap) {
  65. setDataSource(dataSource);
  66. this.sqlMap = sqlMap;
  67. }
  68. /**
  69. * Set the iBATIS Database Layer SqlMap that defines the mapped statements.
  70. */
  71. public void setSqlMap(SqlMap sqlMap) {
  72. this.sqlMap = sqlMap;
  73. }
  74. /**
  75. * Return the iBATIS Database Layer SqlMap that this template works with.
  76. */
  77. public SqlMap getSqlMap() {
  78. return sqlMap;
  79. }
  80. public void afterPropertiesSet() {
  81. super.afterPropertiesSet();
  82. if (this.sqlMap == null) {
  83. throw new IllegalArgumentException("sqlMap is required");
  84. }
  85. }
  86. /**
  87. * Execute the given data access action on the given iBATIS mapped statement.
  88. * @param statementName name of the statement mapped in the iBATIS SqlMap config file
  89. * @param action callback object that specifies the data access action
  90. * @return a result object returned by the action, or null
  91. * @throws DataAccessException in case of SQL Maps errors
  92. */
  93. public Object execute(String statementName, SqlMapCallback action) throws DataAccessException {
  94. MappedStatement stmt = this.sqlMap.getMappedStatement(statementName);
  95. Connection con = DataSourceUtils.getConnection(getDataSource());
  96. try {
  97. return action.doInMappedStatement(stmt, con);
  98. }
  99. catch (SQLException ex) {
  100. throw getExceptionTranslator().translate("SqlMapTemplate", "(mapped statement)", ex);
  101. }
  102. finally {
  103. DataSourceUtils.closeConnectionIfNecessary(con, getDataSource());
  104. }
  105. }
  106. /**
  107. * Execute the given data access action on the given mapped statement,
  108. * expecting a List result.
  109. * @param statementName name of the statement mapped in the iBATIS SqlMap config file
  110. * @param action callback object that specifies the data access action
  111. * @return a List result
  112. * @throws DataAccessException in case of SQL Maps errors
  113. */
  114. public List executeWithListResult(String statementName, SqlMapCallback action)
  115. throws DataAccessException {
  116. return (List) execute(statementName, action);
  117. }
  118. /**
  119. * Execute the given data access action on the given mapped statement,
  120. * expecting a Map result.
  121. * @param statementName name of the statement mapped in the iBATIS SqlMap config file
  122. * @param action callback object that specifies the data access action
  123. * @return a Map result
  124. * @throws DataAccessException in case of SQL Maps errors
  125. */
  126. public Map executeWithMapResult(String statementName, SqlMapCallback action)
  127. throws DataAccessException {
  128. return (Map) execute(statementName, action);
  129. }
  130. public Object executeQueryForObject(String statementName, final Object parameterObject)
  131. throws DataAccessException {
  132. return execute(statementName, new SqlMapCallback() {
  133. public Object doInMappedStatement(MappedStatement stmt, Connection con) throws SQLException {
  134. return stmt.executeQueryForObject(con, parameterObject);
  135. }
  136. });
  137. }
  138. public Object executeQueryForObject(String statementName, final Object parameterObject,
  139. final Object resultObject) throws DataAccessException {
  140. return execute(statementName, new SqlMapCallback() {
  141. public Object doInMappedStatement(MappedStatement stmt, Connection con) throws SQLException {
  142. return stmt.executeQueryForObject(con, parameterObject, resultObject);
  143. }
  144. });
  145. }
  146. public List executeQueryForList(String statementName, final Object parameterObject)
  147. throws DataAccessException {
  148. return executeWithListResult(statementName, new SqlMapCallback() {
  149. public Object doInMappedStatement(MappedStatement stmt, Connection con) throws SQLException {
  150. return stmt.executeQueryForList(con, parameterObject);
  151. }
  152. });
  153. }
  154. public List executeQueryForList(String statementName, final Object parameterObject,
  155. final int skipResults, final int maxResults)
  156. throws DataAccessException {
  157. return executeWithListResult(statementName, new SqlMapCallback() {
  158. public Object doInMappedStatement(MappedStatement stmt, Connection con) throws SQLException {
  159. return stmt.executeQueryForList(con, parameterObject, skipResults, maxResults);
  160. }
  161. });
  162. }
  163. public Map executeQueryForMap(String statementName, final Object parameterObject,
  164. final String keyProperty) throws DataAccessException {
  165. return executeWithMapResult(statementName, new SqlMapCallback() {
  166. public Object doInMappedStatement(MappedStatement stmt, Connection con) throws SQLException {
  167. return stmt.executeQueryForMap(con, parameterObject, keyProperty);
  168. }
  169. });
  170. }
  171. public Map executeQueryForMap(String statementName, final Object parameterObject,
  172. final String keyProperty, final String valueProperty)
  173. throws DataAccessException {
  174. return executeWithMapResult(statementName, new SqlMapCallback() {
  175. public Object doInMappedStatement(MappedStatement stmt, Connection con) throws SQLException {
  176. return stmt.executeQueryForMap(con, parameterObject, keyProperty, valueProperty);
  177. }
  178. });
  179. }
  180. public void executeQueryWithRowHandler(String statementName, final Object parameterObject,
  181. final RowHandler rowHandler) throws DataAccessException {
  182. execute(statementName, new SqlMapCallback() {
  183. public Object doInMappedStatement(MappedStatement stmt, Connection con) throws SQLException {
  184. stmt.executeQueryWithRowHandler(con, parameterObject, rowHandler);
  185. return null;
  186. }
  187. });
  188. }
  189. public int executeUpdate(String statementName, final Object parameterObject)
  190. throws DataAccessException {
  191. Integer result = (Integer) execute(statementName, new SqlMapCallback() {
  192. public Object doInMappedStatement(MappedStatement stmt, Connection con) throws SQLException {
  193. return new Integer(stmt.executeUpdate(con, parameterObject));
  194. }
  195. });
  196. return result.intValue();
  197. }
  198. }