-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
Summary
TableMetaDataProviderFactory
in Spring Framework 6.1.x (used by Spring Boot 3.2.0) lacks a dedicated branch for MySQL and MariaDB. As a result, MySQL connections fall back to GenericTableMetaDataProvider
, which incorrectly reports generatedKeysColumnNameArraySupported = true
. However, MySQL Connector/J does not actually support specifying column names or indices for generated key retrieval - it only accepts these parameters to comply with JDBC API specifications but ignores them entirely.
Evidence from MySQL Connector/J Source Code
Analysis of StatementImpl.java
from MySQL Connector/J reveals that column name/index arrays are converted to boolean flags and discarded:
Line 699-700: execute(String sql, String[] generatedKeyNames)
public boolean execute(String sql, String[] generatedKeyNames) throws SQLException {
return executeInternal(sql, generatedKeyNames != null && generatedKeyNames.length > 0);
}
The generatedKeyNames
array is converted to a boolean and discarded.
Line 694-696: execute(String sql, int[] generatedKeyIndices)
public boolean execute(String sql, int[] generatedKeyIndices) throws SQLException {
return executeInternal(sql, generatedKeyIndices != null && generatedKeyIndices.length > 0);
}
The generatedKeyIndices
array is also converted to a boolean and discarded.
Line 2335-2337: executeLargeUpdate(String sql, String[] columnNames)
public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException {
return executeUpdateInternal(sql, false, columnNames != null && columnNames.length > 0);
}
Same pattern - column names converted to boolean.
Line 2330-2332: executeLargeUpdate(String sql, int[] columnIndexes)
public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException {
return executeUpdateInternal(sql, false, columnIndexes != null && columnIndexes.length > 0);
}
Same pattern - column indexes converted to boolean.
Line 737: Only boolean flag stored
this.retrieveGeneratedKeys = returnGeneratedKeys;
Only a boolean flag is stored in executeInternal()
.
Line 158: Field declaration
protected boolean retrieveGeneratedKeys = false;
The only field related to generated keys is a boolean, not an array of column names or indices.
What This Means
MySQL Connector/J provides these method signatures to comply with JDBC API specifications, but completely ignores the provided column names/indices. When getGeneratedKeys()
is called, it always returns all auto-increment columns regardless of what was specified.
Therefore, Spring Framework's MySqlTableMetaDataProvider
class correctly sets generatedKeysColumnNameArraySupported = false
.
Current Problem
The issue is that while MySqlTableMetaDataProvider
exists in Spring Framework with the correct metadata settings, it is never actually used. TableMetaDataProviderFactory
does not detect MySQL, causing it to fall back to GenericTableMetaDataProvider
, which incorrectly sets generatedKeysColumnNameArraySupported = true
.
Expected Behavior
TableMetaDataProviderFactory
should detect "MySQL" and "MariaDB" (viaDatabaseMetaData.getDatabaseProductName()
)- Return
MySqlTableMetaDataProvider
with correctgeneratedKeysColumnNameArraySupported = false
setting - Consistent with how Oracle, PostgreSQL, Derby, and HSQL have dedicated providers
Proposed Fix
In TableMetaDataProviderFactory.createMetaDataProvider()
, add:
else if ("MySQL".equals(databaseProductName) || "MariaDB".equals(databaseProductName)) {
provider = new MySqlTableMetaDataProvider(databaseMetaData);
}
Insert this before the else
block that creates GenericTableMetaDataProvider
.
Impact
- Ensures accurate metadata representation for MySQL/MariaDB databases
- Correctly reflects MySQL Connector/J's actual capabilities (does not support column name arrays for generated keys)
- Utilizes the existing
MySqlTableMetaDataProvider
class as intended - Maintains consistency with other database-specific provider implementations