1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.executor.statement;
17
18 import java.sql.CallableStatement;
19 import java.sql.Connection;
20 import java.sql.ResultSet;
21 import java.sql.SQLException;
22 import java.sql.Statement;
23 import java.util.List;
24
25 import org.apache.ibatis.cursor.Cursor;
26 import org.apache.ibatis.executor.Executor;
27 import org.apache.ibatis.executor.ExecutorException;
28 import org.apache.ibatis.executor.keygen.KeyGenerator;
29 import org.apache.ibatis.mapping.BoundSql;
30 import org.apache.ibatis.mapping.MappedStatement;
31 import org.apache.ibatis.mapping.ParameterMapping;
32 import org.apache.ibatis.mapping.ParameterMode;
33 import org.apache.ibatis.mapping.ResultSetType;
34 import org.apache.ibatis.session.ResultHandler;
35 import org.apache.ibatis.session.RowBounds;
36 import org.apache.ibatis.type.JdbcType;
37
38
39
40
41 public class CallableStatementHandler extends BaseStatementHandler {
42
43 public CallableStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter,
44 RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
45 super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
46 }
47
48 @Override
49 public int update(Statement statement) throws SQLException {
50 CallableStatement cs = (CallableStatement) statement;
51 cs.execute();
52 int rows = cs.getUpdateCount();
53 Object parameterObject = boundSql.getParameterObject();
54 KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
55 keyGenerator.processAfter(executor, mappedStatement, cs, parameterObject);
56 resultSetHandler.handleOutputParameters(cs);
57 return rows;
58 }
59
60 @Override
61 public void batch(Statement statement) throws SQLException {
62 CallableStatement cs = (CallableStatement) statement;
63 cs.addBatch();
64 }
65
66 @Override
67 public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
68 CallableStatement cs = (CallableStatement) statement;
69 cs.execute();
70 List<E> resultList = resultSetHandler.handleResultSets(cs);
71 resultSetHandler.handleOutputParameters(cs);
72 return resultList;
73 }
74
75 @Override
76 public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
77 CallableStatement cs = (CallableStatement) statement;
78 cs.execute();
79 Cursor<E> resultList = resultSetHandler.handleCursorResultSets(cs);
80 resultSetHandler.handleOutputParameters(cs);
81 return resultList;
82 }
83
84 @Override
85 protected Statement instantiateStatement(Connection connection) throws SQLException {
86 String sql = boundSql.getSql();
87 if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) {
88 return connection.prepareCall(sql);
89 }
90 return connection.prepareCall(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
91 }
92
93 @Override
94 public void parameterize(Statement statement) throws SQLException {
95 registerOutputParameters((CallableStatement) statement);
96 parameterHandler.setParameters((CallableStatement) statement);
97 }
98
99 private void registerOutputParameters(CallableStatement cs) throws SQLException {
100 List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
101 for (int i = 0, n = parameterMappings.size(); i < n; i++) {
102 ParameterMapping parameterMapping = parameterMappings.get(i);
103 if (parameterMapping.getMode() == ParameterMode.OUT || parameterMapping.getMode() == ParameterMode.INOUT) {
104 if (null == parameterMapping.getJdbcType()) {
105 throw new ExecutorException(
106 "The JDBC Type must be specified for output parameter. Parameter: " + parameterMapping.getProperty());
107 }
108 if (parameterMapping.getNumericScale() != null && (parameterMapping.getJdbcType() == JdbcType.NUMERIC
109 || parameterMapping.getJdbcType() == JdbcType.DECIMAL)) {
110 cs.registerOutParameter(i + 1, parameterMapping.getJdbcType().TYPE_CODE, parameterMapping.getNumericScale());
111 } else {
112 if (parameterMapping.getJdbcTypeName() == null) {
113 cs.registerOutParameter(i + 1, parameterMapping.getJdbcType().TYPE_CODE);
114 } else {
115 cs.registerOutParameter(i + 1, parameterMapping.getJdbcType().TYPE_CODE,
116 parameterMapping.getJdbcTypeName());
117 }
118 }
119 }
120 }
121 }
122
123 }