spring-framework
spring-framework copied to clipboard
Optimize parameter matching in TableMetaDataContext
Optimize parameter matching in TableMetaDataContext
Problem
The TableMetaDataContext.matchInParameterValuesWithInsertColumns() method uses a nested loop for case-insensitive parameter matching, resulting in O(n×m) complexity where n = columns and m = parameters.
For each column, when exact matching fails, it iterates through all parameter entries to find case-insensitive matches:
for (String column : this.tableColumns) { // O(n)
Object value = inParameters.get(column);
if (value == null) {
// ... lowercase lookup
if (value == null) {
for (Map.Entry<String, ?> entry : inParameters.entrySet()) { // O(m)
if (column.equalsIgnoreCase(entry.getKey())) {
value = entry.getValue();
break;
}
}
}
}
values.add(value);
}
This becomes expensive with many columns and parameters (e.g., 100 columns × 1000 parameters = 100K iterations).
Solution
Pre-compute a case-insensitive lookup map, reducing complexity from O(n×m) to O(n+m):
// Build lookup map once - O(m)
Map<String, Object> caseInsensitiveLookup = new HashMap<>(inParameters.size());
for (Map.Entry<String, ?> entry : inParameters.entrySet()) {
caseInsensitiveLookup.put(entry.getKey().toLowerCase(Locale.ROOT), entry.getValue());
}
for (String column : this.tableColumns) { // O(n)
Object value = inParameters.get(column);
if (value == null) {
value = inParameters.get(column.toLowerCase(Locale.ROOT));
if (value == null) {
value = caseInsensitiveLookup.get(column.toLowerCase(Locale.ROOT)); // O(1)
}
}
values.add(value);
}
Performance Impact
- Before: O(n×m) - quadratic growth
- After: O(n+m) - linear growth
- Applications affected: SimpleJdbcInsert users with many columns/parameters
Testing
- ✅ All existing tests pass (no behavior change)
- ✅ Verified case-sensitive/insensitive matching logic preserved