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 boolean executeBefore;
37 private 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 if (keyProperties != null) {
65
66
67 Executor keyExecutor = configuration.newExecutor(executor.getTransaction(), ExecutorType.SIMPLE);
68 List<Object> values = keyExecutor.query(keyStatement, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
69 if (values.size() == 0) {
70 throw new ExecutorException("SelectKey returned no data.");
71 } else 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 }
89 } catch (ExecutorException e) {
90 throw e;
91 } catch (Exception e) {
92 throw new ExecutorException("Error selecting key or setting result to parameter object. Cause: " + e, e);
93 }
94 }
95
96 private void handleMultipleProperties(String[] keyProperties,
97 MetaObject metaParam, MetaObject metaResult) {
98 String[] keyColumns = keyStatement.getKeyColumns();
99
100 if (keyColumns == null || keyColumns.length == 0) {
101
102 for (int i = 0; i < keyProperties.length; i++) {
103 setValue(metaParam, keyProperties[i], metaResult.getValue(keyProperties[i]));
104 }
105 } else {
106 if (keyColumns.length != keyProperties.length) {
107 throw new ExecutorException("If SelectKey has key columns, the number must match the number of key properties.");
108 }
109 for (int i = 0; i < keyProperties.length; i++) {
110 setValue(metaParam, keyProperties[i], metaResult.getValue(keyColumns[i]));
111 }
112 }
113 }
114
115 private void setValue(MetaObject metaParam, String property, Object value) {
116 if (metaParam.hasSetter(property)) {
117 metaParam.setValue(property, value);
118 } else {
119 throw new ExecutorException("No setter found for the keyProperty '" + property + "' in " + metaParam.getOriginalObject().getClass().getName() + ".");
120 }
121 }
122 }