1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.executor.keygen;
17
18 import java.sql.Statement;
19 import java.util.List;
20
21 import org.apache.ibatis.executor.Executor;
22 import org.apache.ibatis.executor.ExecutorException;
23 import org.apache.ibatis.mapping.MappedStatement;
24 import org.apache.ibatis.reflection.MetaObject;
25 import org.apache.ibatis.session.Configuration;
26 import org.apache.ibatis.session.ExecutorType;
27 import org.apache.ibatis.session.RowBounds;
28
29
30
31
32
33 public class SelectKeyGenerator implements KeyGenerator {
34
35 public static final String SELECT_KEY_SUFFIX = "!selectKey";
36 private final boolean executeBefore;
37 private final MappedStatement keyStatement;
38
39 public SelectKeyGenerator(MappedStatement keyStatement, boolean executeBefore) {
40 this.executeBefore = executeBefore;
41 this.keyStatement = keyStatement;
42 }
43
44 @Override
45 public void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
46 if (executeBefore) {
47 processGeneratedKeys(executor, ms, parameter);
48 }
49 }
50
51 @Override
52 public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
53 if (!executeBefore) {
54 processGeneratedKeys(executor, ms, parameter);
55 }
56 }
57
58 private void processGeneratedKeys(Executor executor, MappedStatement ms, Object parameter) {
59 try {
60 if (parameter != null && keyStatement != null && keyStatement.getKeyProperties() != null) {
61 String[] keyProperties = keyStatement.getKeyProperties();
62 final Configuration configuration = ms.getConfiguration();
63 final MetaObject metaParam = configuration.newMetaObject(parameter);
64
65
66 Executor keyExecutor = configuration.newExecutor(executor.getTransaction(), ExecutorType.SIMPLE);
67 List<Object> values = keyExecutor.query(keyStatement, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
68 if (values.isEmpty()) {
69 throw new ExecutorException("SelectKey returned no data.");
70 }
71 if (values.size() > 1) {
72 throw new ExecutorException("SelectKey returned more than one value.");
73 } else {
74 MetaObject metaResult = configuration.newMetaObject(values.get(0));
75 if (keyProperties.length == 1) {
76 if (metaResult.hasGetter(keyProperties[0])) {
77 setValue(metaParam, keyProperties[0], metaResult.getValue(keyProperties[0]));
78 } else {
79
80
81 setValue(metaParam, keyProperties[0], values.get(0));
82 }
83 } else {
84 handleMultipleProperties(keyProperties, metaParam, metaResult);
85 }
86 }
87 }
88 } catch (ExecutorException e) {
89 throw e;
90 } catch (Exception e) {
91 throw new ExecutorException("Error selecting key or setting result to parameter object. Cause: " + e, e);
92 }
93 }
94
95 private void handleMultipleProperties(String[] keyProperties, MetaObject metaParam, MetaObject metaResult) {
96 String[] keyColumns = keyStatement.getKeyColumns();
97
98 if (keyColumns == null || keyColumns.length == 0) {
99
100 for (String keyProperty : keyProperties) {
101 setValue(metaParam, keyProperty, metaResult.getValue(keyProperty));
102 }
103 } else {
104 if (keyColumns.length != keyProperties.length) {
105 throw new ExecutorException(
106 "If SelectKey has key columns, the number must match the number of key properties.");
107 }
108 for (int i = 0; i < keyProperties.length; i++) {
109 setValue(metaParam, keyProperties[i], metaResult.getValue(keyColumns[i]));
110 }
111 }
112 }
113
114 private void setValue(MetaObject metaParam, String property, Object value) {
115 if (!metaParam.hasSetter(property)) {
116 throw new ExecutorException("No setter found for the keyProperty '" + property + "' in "
117 + metaParam.getOriginalObject().getClass().getName() + ".");
118 }
119 metaParam.setValue(property, value);
120 }
121 }