15
15
*/
16
16
package org .apache .ibatis .session ;
17
17
18
+ import java .sql .SQLException ;
18
19
import java .util .Arrays ;
19
20
import java .util .Collection ;
20
21
import java .util .HashMap ;
23
24
import java .util .LinkedList ;
24
25
import java .util .List ;
25
26
import java .util .Map ;
27
+ import java .util .Objects ;
26
28
import java .util .Properties ;
27
29
import java .util .Set ;
28
30
import java .util .concurrent .ConcurrentHashMap ;
69
71
import org .apache .ibatis .logging .slf4j .Slf4jImpl ;
70
72
import org .apache .ibatis .logging .stdout .StdOutImpl ;
71
73
import org .apache .ibatis .mapping .BoundSql ;
74
+ import org .apache .ibatis .mapping .DatabaseIdProvider ;
72
75
import org .apache .ibatis .mapping .Environment ;
73
76
import org .apache .ibatis .mapping .MappedStatement ;
74
77
import org .apache .ibatis .mapping .ParameterMap ;
@@ -108,6 +111,7 @@ public class Configuration {
108
111
protected boolean safeResultHandlerEnabled = true ;
109
112
protected boolean mapUnderscoreToCamelCase ;
110
113
protected boolean aggressiveLazyLoading ;
114
+ protected boolean multipleResultSetsEnabled = true ;
111
115
protected boolean useGeneratedKeys ;
112
116
protected boolean useColumnLabel = true ;
113
117
protected boolean cacheEnabled = true ;
@@ -117,6 +121,7 @@ public class Configuration {
117
121
protected boolean shrinkWhitespacesInSql ;
118
122
protected boolean nullableOnForEach ;
119
123
protected boolean argNameBasedConstructorAutoMapping ;
124
+ protected boolean supportDynamicRoutingDataSource ;
120
125
121
126
protected String logPrefix ;
122
127
protected Class <? extends Log > logImpl ;
@@ -133,6 +138,7 @@ public class Configuration {
133
138
protected AutoMappingBehavior autoMappingBehavior = AutoMappingBehavior .PARTIAL ;
134
139
protected AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior = AutoMappingUnknownColumnBehavior .NONE ;
135
140
141
+ protected DatabaseIdProvider databaseIdProvider ;
136
142
protected Properties variables = new Properties ();
137
143
protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory ();
138
144
protected ObjectFactory objectFactory = new DefaultObjectFactory ();
@@ -349,6 +355,29 @@ public void setDatabaseId(String databaseId) {
349
355
this .databaseId = databaseId ;
350
356
}
351
357
358
+ public boolean getSupportDynamicRoutingDataSource () {
359
+ return this .supportDynamicRoutingDataSource ;
360
+ }
361
+
362
+ public void setSupportDynamicRoutingDataSource (Boolean supportDynamicRoutingDataSource ) {
363
+ this .supportDynamicRoutingDataSource = supportDynamicRoutingDataSource ;
364
+ }
365
+
366
+ public DatabaseIdProvider getDatabaseIdProvider () {
367
+ return databaseIdProvider ;
368
+ }
369
+
370
+ public void setDatabaseIdProvider (DatabaseIdProvider databaseIdProvider ) {
371
+ this .databaseIdProvider = databaseIdProvider ;
372
+ }
373
+
374
+ public String getCurrentDatabaseId () throws SQLException {
375
+ if (supportDynamicRoutingDataSource && databaseIdProvider != null ) {
376
+ return databaseIdProvider .getDatabaseId (environment .getDataSource ());
377
+ }
378
+ return this .getDatabaseId ();
379
+ }
380
+
352
381
public Class <?> getConfigurationFactory () {
353
382
return configurationFactory ;
354
383
}
@@ -455,20 +484,12 @@ public void setAggressiveLazyLoading(boolean aggressiveLazyLoading) {
455
484
this .aggressiveLazyLoading = aggressiveLazyLoading ;
456
485
}
457
486
458
- /**
459
- * @deprecated You can safely remove the call to this method as this option had no effect.
460
- */
461
- @ Deprecated
462
487
public boolean isMultipleResultSetsEnabled () {
463
- return true ;
488
+ return multipleResultSetsEnabled ;
464
489
}
465
490
466
- /**
467
- * @deprecated You can safely remove the call to this method as this option had no effect.
468
- */
469
- @ Deprecated
470
491
public void setMultipleResultSetsEnabled (boolean multipleResultSetsEnabled ) {
471
- // nop
492
+ this . multipleResultSetsEnabled = multipleResultSetsEnabled ;
472
493
}
473
494
474
495
public Set <String > getLazyLoadTriggerMethods () {
@@ -831,7 +852,12 @@ public boolean hasParameterMap(String id) {
831
852
}
832
853
833
854
public void addMappedStatement (MappedStatement ms ) {
834
- mappedStatements .put (ms .getId (), ms );
855
+ String id = ms .getId ();
856
+ if (this .getSupportDynamicRoutingDataSource () && Objects .nonNull (ms .getDatabaseId ())
857
+ && ms .getDatabaseId ().trim ().length () > 0 ) {
858
+ id = id + "#" + ms .getDatabaseId ();
859
+ }
860
+ mappedStatements .put (id , ms );
835
861
}
836
862
837
863
public Collection <String > getMappedStatementNames () {
@@ -920,7 +946,29 @@ public MappedStatement getMappedStatement(String id, boolean validateIncompleteS
920
946
if (validateIncompleteStatements ) {
921
947
buildAllStatements ();
922
948
}
923
- return mappedStatements .get (id );
949
+ MappedStatement statement = null ;
950
+ try {
951
+ statement = mappedStatements .get (this .getMappedStatementId (id ));
952
+ } catch (IllegalArgumentException e ) {
953
+ if (this .getSupportDynamicRoutingDataSource ()) {
954
+ statement = mappedStatements .get (id );
955
+ } else {
956
+ throw e ;
957
+ }
958
+ }
959
+
960
+ return statement ;
961
+ }
962
+
963
+ protected String getMappedStatementId (String id ) {
964
+ try {
965
+ String databaseId = this .getCurrentDatabaseId ();
966
+ if (this .getSupportDynamicRoutingDataSource () && Objects .nonNull (databaseId )) {
967
+ return id + "#" + databaseId ;
968
+ }
969
+ } catch (SQLException ignore ) {
970
+ }
971
+ return id ;
924
972
}
925
973
926
974
public Map <String , XNode > getSqlFragments () {
@@ -959,7 +1007,8 @@ public boolean hasStatement(String statementName, boolean validateIncompleteStat
959
1007
if (validateIncompleteStatements ) {
960
1008
buildAllStatements ();
961
1009
}
962
- return mappedStatements .containsKey (statementName );
1010
+ return mappedStatements .containsKey (this .getMappedStatementId (statementName ))
1011
+ || this .getSupportDynamicRoutingDataSource () && mappedStatements .containsKey (statementName );
963
1012
}
964
1013
965
1014
public void addCacheRef (String namespace , String referencedNamespace ) {
@@ -1113,7 +1162,6 @@ protected static class StrictMap<V> extends ConcurrentHashMap<String, V> {
1113
1162
private static final long serialVersionUID = -4950446264854982944L ;
1114
1163
private final String name ;
1115
1164
private BiFunction <V , V , String > conflictMessageProducer ;
1116
- private static final Object AMBIGUITY_INSTANCE = new Object ();
1117
1165
1118
1166
public StrictMap (String name , int initialCapacity , float loadFactor ) {
1119
1167
super (initialCapacity , loadFactor );
@@ -1163,7 +1211,7 @@ public V put(String key, V value) {
1163
1211
if (super .get (shortKey ) == null ) {
1164
1212
super .put (shortKey , value );
1165
1213
} else {
1166
- super .put (shortKey , (V ) AMBIGUITY_INSTANCE );
1214
+ super .put (shortKey , (V ) new Ambiguity ( shortKey ) );
1167
1215
}
1168
1216
}
1169
1217
return super .put (key , value );
@@ -1184,13 +1232,25 @@ public V get(Object key) {
1184
1232
if (value == null ) {
1185
1233
throw new IllegalArgumentException (name + " does not contain value for " + key );
1186
1234
}
1187
- if (AMBIGUITY_INSTANCE == value ) {
1188
- throw new IllegalArgumentException (key + " is ambiguous in " + name
1235
+ if (value instanceof Ambiguity ) {
1236
+ throw new IllegalArgumentException ((( Ambiguity ) value ). getSubject () + " is ambiguous in " + name
1189
1237
+ " (try using the full name including the namespace, or rename one of the entries)" );
1190
1238
}
1191
1239
return value ;
1192
1240
}
1193
1241
1242
+ protected static class Ambiguity {
1243
+ private final String subject ;
1244
+
1245
+ public Ambiguity (String subject ) {
1246
+ this .subject = subject ;
1247
+ }
1248
+
1249
+ public String getSubject () {
1250
+ return subject ;
1251
+ }
1252
+ }
1253
+
1194
1254
private String getShortName (String key ) {
1195
1255
final String [] keyParts = key .split ("\\ ." );
1196
1256
return keyParts [keyParts .length - 1 ];
0 commit comments