3
3
import org .apache .ibatis .cache .CacheKey ;
4
4
import org .apache .ibatis .cache .impl .PerpetualCache ;
5
5
import static org .apache .ibatis .executor .ExecutionPlaceholder .EXECUTION_PLACEHOLDER ;
6
- import org .apache .ibatis .mapping .BoundSql ;
7
- import org .apache .ibatis .mapping .MappedStatement ;
8
- import org .apache .ibatis .mapping .ParameterMapping ;
6
+
7
+ import org .apache .ibatis .mapping .*;
9
8
import org .apache .ibatis .reflection .MetaObject ;
10
9
import org .apache .ibatis .session .ResultHandler ;
11
10
import org .apache .ibatis .session .RowBounds ;
@@ -24,6 +23,7 @@ public abstract class BaseExecutor implements Executor {
24
23
25
24
protected ConcurrentLinkedQueue <DeferredLoad > deferredLoads ;
26
25
protected PerpetualCache localCache ;
26
+ protected PerpetualCache localOutputParameterCache ;
27
27
protected Configuration configuration ;
28
28
29
29
protected int queryStack = 0 ;
@@ -35,6 +35,7 @@ protected BaseExecutor(Configuration configuration, Transaction transaction) {
35
35
this .transaction = transaction ;
36
36
this .deferredLoads = new ConcurrentLinkedQueue <DeferredLoad >();
37
37
this .localCache = new PerpetualCache ("LocalCache" );
38
+ this .localOutputParameterCache = new PerpetualCache ("LocalOutputParameterCache" );
38
39
this .closed = false ;
39
40
this .configuration = configuration ;
40
41
}
@@ -57,6 +58,7 @@ public void close(boolean forceRollback) {
57
58
transaction = null ;
58
59
deferredLoads = null ;
59
60
localCache = null ;
61
+ localOutputParameterCache = null ;
60
62
batchResults = null ;
61
63
closed = true ;
62
64
}
@@ -86,17 +88,11 @@ public List query(MappedStatement ms, Object parameter, RowBounds rowBounds, Res
86
88
try {
87
89
queryStack ++;
88
90
CacheKey key = createCacheKey (ms , parameter , rowBounds );
89
- final List cachedList = (List ) localCache .getObject (key );
90
- if (cachedList != null ) {
91
- list = cachedList ;
91
+ list = (List ) localCache .getObject (key );
92
+ if (list != null ) {
93
+ handleLocallyCachedOutputParameters ( ms , key , parameter ) ;
92
94
} else {
93
- localCache .putObject (key , EXECUTION_PLACEHOLDER );
94
- try {
95
- list = doQuery (ms , parameter , rowBounds , resultHandler );
96
- } finally {
97
- localCache .removeObject (key );
98
- }
99
- localCache .putObject (key , list );
95
+ list = queryFromDatabase (ms , parameter , rowBounds , resultHandler , key );
100
96
}
101
97
} finally {
102
98
queryStack --;
@@ -173,6 +169,7 @@ public void rollback(boolean required) throws SQLException {
173
169
public void clearLocalCache () {
174
170
if (!closed ) {
175
171
localCache .clear ();
172
+ localOutputParameterCache .clear ();
176
173
}
177
174
}
178
175
@@ -195,6 +192,38 @@ protected void closeStatement(Statement statement) {
195
192
}
196
193
}
197
194
195
+ private void handleLocallyCachedOutputParameters (MappedStatement ms , CacheKey key , Object parameter ) {
196
+ if (ms .getStatementType () == StatementType .CALLABLE ) {
197
+ final Object cachedParameter = localOutputParameterCache .getObject (key );
198
+ if (cachedParameter != null && parameter != null ) {
199
+ final MetaObject metaCachedParameter = MetaObject .forObject (cachedParameter );
200
+ final MetaObject metaParameter = MetaObject .forObject (parameter );
201
+ for (ParameterMapping parameterMapping : ms .getBoundSql (parameter ).getParameterMappings ()) {
202
+ if (parameterMapping .getMode () != ParameterMode .IN ) {
203
+ final String parameterName = parameterMapping .getProperty ();
204
+ final Object cachedValue = metaCachedParameter .getValue (parameterName );
205
+ metaParameter .setValue (parameterName , cachedValue );
206
+ }
207
+ }
208
+ }
209
+ }
210
+ }
211
+
212
+ private List queryFromDatabase (MappedStatement ms , Object parameter , RowBounds rowBounds , ResultHandler resultHandler , CacheKey key ) throws SQLException {
213
+ List list ;
214
+ localCache .putObject (key , EXECUTION_PLACEHOLDER );
215
+ try {
216
+ list = doQuery (ms , parameter , rowBounds , resultHandler );
217
+ } finally {
218
+ localCache .removeObject (key );
219
+ }
220
+ localCache .putObject (key , list );
221
+ if (ms .getStatementType () == StatementType .CALLABLE ) {
222
+ localOutputParameterCache .putObject (key , parameter );
223
+ }
224
+ return list ;
225
+ }
226
+
198
227
private class DeferredLoad {
199
228
200
229
MappedStatement mappedStatement ;
0 commit comments