View Javadoc
1   /**
2    *    Copyright 2009-2015 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.apache.ibatis.executor.keygen;
17  
18  import java.sql.ResultSet;
19  import java.sql.ResultSetMetaData;
20  import java.sql.SQLException;
21  import java.sql.Statement;
22  import java.util.ArrayList;
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.mapping.MappedStatement;
28  import org.apache.ibatis.reflection.MetaObject;
29  import org.apache.ibatis.session.Configuration;
30  import org.apache.ibatis.type.TypeHandler;
31  import org.apache.ibatis.type.TypeHandlerRegistry;
32  
33  /**
34   * @author Clinton Begin
35   */
36  public class Jdbc3KeyGenerator implements KeyGenerator {
37  
38    @Override
39    public void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
40      // do nothing
41    }
42  
43    @Override
44    public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
45      List<Object> parameters = new ArrayList<Object>();
46      parameters.add(parameter);
47      processBatch(ms, stmt, parameters);
48    }
49  
50    public void processBatch(MappedStatement ms, Statement stmt, List<Object> parameters) {
51      ResultSet rs = null;
52      try {
53        rs = stmt.getGeneratedKeys();
54        final Configuration configuration = ms.getConfiguration();
55        final TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
56        final String[] keyProperties = ms.getKeyProperties();
57        final ResultSetMetaData rsmd = rs.getMetaData();
58        TypeHandler<?>[] typeHandlers = null;
59        if (keyProperties != null && rsmd.getColumnCount() >= keyProperties.length) {
60          for (Object parameter : parameters) {
61            // there should be one row for each statement (also one for each parameter)
62            if (!rs.next()) {
63              break;
64            }
65            final MetaObject metaParam = configuration.newMetaObject(parameter);
66            if (typeHandlers == null) {
67              typeHandlers = getTypeHandlers(typeHandlerRegistry, metaParam, keyProperties);
68            }
69            populateKeys(rs, metaParam, keyProperties, typeHandlers);
70          }
71        }
72      } catch (Exception e) {
73        throw new ExecutorException("Error getting generated key or setting result to parameter object. Cause: " + e, e);
74      } finally {
75        if (rs != null) {
76          try {
77            rs.close();
78          } catch (Exception e) {
79            // ignore
80          }
81        }
82      }
83    }
84  
85    private TypeHandler<?>[] getTypeHandlers(TypeHandlerRegistry typeHandlerRegistry, MetaObject metaParam, String[] keyProperties) {
86      TypeHandler<?>[] typeHandlers = new TypeHandler<?>[keyProperties.length];
87      for (int i = 0; i < keyProperties.length; i++) {
88        if (metaParam.hasSetter(keyProperties[i])) {
89          Class<?> keyPropertyType = metaParam.getSetterType(keyProperties[i]);
90          TypeHandler<?> th = typeHandlerRegistry.getTypeHandler(keyPropertyType);
91          typeHandlers[i] = th;
92        }
93      }
94      return typeHandlers;
95    }
96  
97    private void populateKeys(ResultSet rs, MetaObject metaParam, String[] keyProperties, TypeHandler<?>[] typeHandlers) throws SQLException {
98      for (int i = 0; i < keyProperties.length; i++) {
99        TypeHandler<?> th = typeHandlers[i];
100       if (th != null) {
101         Object value = th.getResult(rs, i + 1);
102         metaParam.setValue(keyProperties[i], value);
103       }
104     }
105   }
106 
107 }