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.size() == 0) {
69 throw new ExecutorException("SelectKey returned no data.");
70 } else if (values.size() > 1) {
71 throw new ExecutorException("SelectKey returned more than one value.");
72 } else {
73 MetaObject metaResult = configuration.newMetaObject(values.get(0));
74 if (keyProperties.length == 1) {
75 if (metaResult.hasGetter(keyProperties[0])) {
76 setValue(metaParam, keyProperties[0], metaResult.getValue(keyProperties[0]));
77 } else {
78
79
80 setValue(metaParam, keyProperties[0], values.get(0));
81 }
82 } else {
83 handleMultipleProperties(keyProperties, metaParam, metaResult);
84 }
85 }
86 }
87 } catch (ExecutorException e) {
88 throw e;
89 } catch (Exception e) {
90 throw new ExecutorException("Error selecting key or setting result to parameter object. Cause: " + e, e);
91 }
92 }
93
94 private void handleMultipleProperties(String[] keyProperties,
95 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("If SelectKey has key columns, the number must match the number of key properties.");
106 }
107 for (int i = 0; i < keyProperties.length; i++) {
108 setValue(metaParam, keyProperties[i], metaResult.getValue(keyColumns[i]));
109 }
110 }
111 }
112
113 private void setValue(MetaObject metaParam, String property, Object value) {
114 if (metaParam.hasSetter(property)) {
115 metaParam.setValue(property, value);
116 } else {
117 throw new ExecutorException("No setter found for the keyProperty '" + property + "' in " + metaParam.getOriginalObject().getClass().getName() + ".");
118 }
119 }
120 }