Change various JDBC abstraction classes to allow them to work with JdbcOperations instead of JdbcTemplate. This allows the usage of custom JdbcOperations that for example perform additional logging.
The following classes have been updated
- AbstractJdbcCall
- SimpleJdbcCall
- AbstractJdbcInsert
- SimpleJdbcInsert
- JdbcBeanDefinitionReader
- RdbmsOperation
- StoredProcedure
This is a backwards compatible change. All existing JdbcTemplate methods are kept.
Closes gh-23065
Comment From: marschall
This change is backwards compatible.
NamedParameterJdbcTemplate#getJdbcTemplate() already throws an exception when the JdbcOperations implementation is not a JdbcTemplate so I went for the same behavior.
This is similar to #8440 and I exclude JdbcDaoSupport for that reason.
Comment From: jhoeller
Coming back to this, I'm wondering how beneficial it is to decorate JdbcOperations - rather than extend JdbcTemplate directly and add some logging in overridden methods, along the lines of #23106... RdbmsOperation for example is quite a JdbcTemplate wrapper, it is rather natural to keep interacting with JdbcTemplate proper there. Maybe we can make it easier to add custom logging in a JdbcTemplate subclass, we could consider a revision in that direction instead.
Comment From: jhoeller
From the perspective above, I'm closing this PR for the time being. A separate issue for extending JdbcTemplate along those lines would be welcome, although the existing extension possibilities might be sufficient for those purposes already.
Comment From: marschall
Favor composition over inheritance :-)
For reference, here's our JdbcOperations implementation https://github.com/marschall/jfr-jdbctemplate/blob/master/src/main/java/com/github/marschall/jfr/jdbctemplate/JfrJdbcOperations.java. At first glance it looks like the implementation would be simpler with a logging callback where we get the SQL query, row count and query duration without having to extract it ourselves. However due to the design of JFR we can not set the duration of an event explicitly. Instead we need to create and start an event before the operation and stop it afterwards. So we would need two callbacks, one before the execution that returns an event and a second after the execution that gets passed the event. I can't speak to the need of other monitoring solutions.