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, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
44 super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
45 }
46
47 @Override
48 public int update(Statement statement) throws SQLException {
49 CallableStatement cs = (CallableStatement) statement;
50 cs.execute();
51 int rows = cs.getUpdateCount();
52 Object parameterObject = boundSql.getParameterObject();
53 KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
54 keyGenerator.processAfter(executor, mappedStatement, cs, parameterObject);
55 resultSetHandler.handleOutputParameters(cs);
56 return rows;
57 }
58
59 @Override
60 public void batch(Statement statement) throws SQLException {
61 CallableStatement cs = (CallableStatement) statement;
62 cs.addBatch();
63 }
64
65 @Override
66 public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
67 CallableStatement cs = (CallableStatement) statement;
68 cs.execute();
69 List<E> resultList = resultSetHandler.handleResultSets(cs);
70 resultSetHandler.handleOutputParameters(cs);
71 return resultList;
72 }
73
74 @Override
75 public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
76 CallableStatement cs = (CallableStatement) statement;
77 cs.execute();
78 Cursor<E> resultList = resultSetHandler.handleCursorResultSets(cs);
79 resultSetHandler.handleOutputParameters(cs);
80 return resultList;
81 }
82
83 @Override
84 protected Statement instantiateStatement(Connection connection) throws SQLException {
85 String sql = boundSql.getSql();
86 if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) {
87 return connection.prepareCall(sql);
88 } else {
89 return connection.prepareCall(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
90 }
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("The JDBC Type must be specified for output parameter. Parameter: " + parameterMapping.getProperty());
106 } else {
107 if (parameterMapping.getNumericScale() != null && (parameterMapping.getJdbcType() == JdbcType.NUMERIC || parameterMapping.getJdbcType() == JdbcType.DECIMAL)) {
108 cs.registerOutParameter(i + 1, parameterMapping.getJdbcType().TYPE_CODE, parameterMapping.getNumericScale());
109 } else {
110 if (parameterMapping.getJdbcTypeName() == null) {
111 cs.registerOutParameter(i + 1, parameterMapping.getJdbcType().TYPE_CODE);
112 } else {
113 cs.registerOutParameter(i + 1, parameterMapping.getJdbcType().TYPE_CODE, parameterMapping.getJdbcTypeName());
114 }
115 }
116 }
117 }
118 }
119 }
120
121 }