Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SimpleJdbcInsert (sporadically) does not insert all columns #26486

Closed
j8zdev opened this issue Feb 1, 2021 · 4 comments
Closed

SimpleJdbcInsert (sporadically) does not insert all columns #26486

j8zdev opened this issue Feb 1, 2021 · 4 comments
Assignees
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) status: backported An issue that has been backported to maintenance branches type: bug A general bug
Milestone

Comments

@j8zdev
Copy link

j8zdev commented Feb 1, 2021

Affects: Spring Framework 5.3.3


When using SimpleJdbcInsert without usingColumns(), it tries to determine the columns from database metadata. When there is any exception, a warning is logged, but otherwise the exception is ignored:

catch (SQLException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Error while retrieving meta-data for procedure columns: " + ex);
}
}

This is fine as long as the exception occurs before any metadata could be read, because later this will cause an exception when generating the SQL string:

throw new InvalidDataAccessApiUsageException("Unable to locate columns for table '" +
getTableName() + "' so an insert statement can't be generated");

However, when an SQLException occurs in columns.next() ...

... after the first column metadata has already been read and added to this.callParameterMetaData, it continues with an incomplete list of columns and only inserts these, ignoring any other columns.

We have experienced this problem in our system very sporadically, and it's especially dangerous, because SimpleJdbcInsert.execute() (as long as there are no NOT NULL constraints for the columns) returns seemingly successfully, so the transactions are committed with incomplete/corrupted data.

It seems like we can work around the problem by calling usingColumns() for all uses of SimpleJdbcInsert.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Feb 1, 2021
@sbrannen sbrannen added the in: data Issues in data modules (jdbc, orm, oxm, tx) label Feb 1, 2021
@sbrannen sbrannen changed the title SimpleJdbcTemplate (sporadically) does not insert all columns SimpleJdbcInsert (sporadically) does not insert all columns Feb 2, 2021
@sbrannen
Copy link
Member

sbrannen commented Feb 2, 2021

SimpleJdbcTemplate no longer exists in Spring Framework 5.3. So I assume you meant to refer to SimpleJdbcInsert. I've edited this issue's title and description accordingly.

In light of that, did you perhaps mean to provide a link to GenericTableMetaDataProvider instead of GenericCallMetaDataProvider?

Or are you using SimpleJdbcCall instead of SimpleJdbcInsert?

@sbrannen sbrannen added the status: waiting-for-feedback We need additional information before we can continue label Feb 2, 2021
@sbrannen sbrannen self-assigned this Feb 2, 2021
@sbrannen
Copy link
Member

sbrannen commented Feb 3, 2021

Or are you using SimpleJdbcCall instead of SimpleJdbcInsert?

In any case, it looks like GenericCallMetaDataProvider.processProcedureColumns(DatabaseMetaData, String, String, String) and GenericTableMetaDataProvider.processTableColumns(DatabaseMetaData, TableMetaData) have similar constructs that can result in partial metadata being recorded.

So I'll investigate both.

@j8zdev
Copy link
Author

j8zdev commented Feb 3, 2021

Sorry for the confusion. We're actually using SimpleJdbcInsert and I accidently linked to a similar but wrong line in GenericCallMetaDataProvider instead of GenericTableMetaDataProvider. But as you noticed, probably both are affected.

Thanks for investigating!

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Feb 3, 2021
@sbrannen sbrannen added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Feb 3, 2021
@sbrannen sbrannen added this to the 5.3.4 milestone Feb 3, 2021
@sbrannen sbrannen added the for: backport-to-5.2.x Marks an issue as a candidate for backport to 5.2.x label Feb 3, 2021
@spring-projects-issues spring-projects-issues added status: backported An issue that has been backported to maintenance branches and removed for: backport-to-5.2.x Marks an issue as a candidate for backport to 5.2.x labels Feb 3, 2021
@sbrannen sbrannen removed the status: feedback-provided Feedback has been provided label Feb 3, 2021
sbrannen added a commit that referenced this issue Feb 4, 2021
Prior to this commit, if an SQLException was thrown while retrieving
column metadata from the database, SimpleJdbcInsert would generate an
INSERT statement that was syntactically valid but missing columns,
which could lead to data silently missing in the database (for nullable
columns).

This commit fixes this by clearing all collected column metadata if an
SQLException is thrown while processing the metadata. The result is
that an InvalidDataAccessApiUsageException will be thrown later while
generating the INSERT statement. The exception message now contains an
additional hint to make use of SimpleJdbcInsert#usingColumns() in order
to ensure that all required columns are included in the generated
INSERT statement.

SimpleJdbcCall can also encounter an SQLException while retrieving
column metadata for a stored procedure/function, but an exception is
not thrown since a later invocation of the stored procedure/function
will likely fail anyway due to missing arguments. Consequently, this
commit only improves the warning level log message by including a hint
to make use of SimpleJdbcCall#addDeclaredParameter().

Closes gh-26486
@sbrannen
Copy link
Member

sbrannen commented Feb 4, 2021

The fix has been merged into master (5.3.x) and 5.2.x.

Feel free to try it out in the latest 5.3.4 and 5.2.13 snapshots.

This was referenced Mar 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) status: backported An issue that has been backported to maintenance branches type: bug A general bug
Projects
None yet
Development

No branches or pull requests

3 participants