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