It would be great if JdbcOperations
or JdbcTemplate
could be enhanced to support String Template.
The easiest way to support this is to provide a StringTemplate.Processor<PreparedStatementCreator, DataAccessException>
implementation, ideally as a constant somewhere. Something like this can already be achieved today with PreparedStatementCreatorFactory
but is a bit awkward due to the need to explicitly register SqlParameter
with type TYPE_UNKNOWN
.
Example:
@Transactional
@SpringJUnitConfig(H2Configuration.class)
class JdbcTemplateTests {
private static final StringTemplate.Processor<PreparedStatementCreator, DataAccessException> SQL = new PreparedStatementCreatorTemplateProcessor();
@Autowired
private DataSource dataSource;
private JdbcOperations jdbcTemplate;
@BeforeEach
void setUp() {
this.jdbcTemplate = new JdbcTemplate(this.dataSource);
}
@Test
void query() {
String name = "ok";
List<String> names = this.jdbcTemplate.query(SQL."""
SELECT \{name}
FROM dual
""", (rs, i) -> rs.getString(1));
assertEquals(List.of(name), names);
}
static final class PreparedStatementCreatorTemplateProcessor implements StringTemplate.Processor<PreparedStatementCreator, DataAccessException> {
public PreparedStatementCreator process(StringTemplate st) {
String sql = String.join("?", st.fragments());
PreparedStatementCreatorFactory factory = new PreparedStatementCreatorFactory(sql);
List<Object> parameters = st.values();
for (Object parameter : parameters) {
factory.addParameter(new SqlParameter(JdbcUtils.TYPE_UNKNOWN));
}
return factory.newPreparedStatementCreator(parameters);
}
}
}
It's still a bit awkward as only methods accepting PreparedStatementCreator
would work.
Comment From: simonbasle
Thanks for the suggestion @marschall. Given that String Templates are still a preview feature in Java 21 and that Spring 6's baseline is Java 17, it would be a challenge to integrate String Templates into the API directly at this stage.
Do you feel that your proposed PreparedStatementCreatorTemplateProcessor
is too much boilerplate for your codebase?
Btw, one thing that I think could be improved wrt TYPE_UNKNOWN
would be using StatementCreatorUtils
like so:
factory.addParameter(new SqlParameter(StatementCreatorUtils.javaTypeToSqlParameterType(parameter.getClass())));
Comment From: marschall
Thanks for the suggestion @marschall. Given that String Templates are still a preview feature in Java 21 and that Spring 6's baseline is Java 17, it would be a challenge to integrate String Templates into the API directly at this stage.
Fair enough. Maybe something that can be visited again should String Templates become fully supported.
Do you feel that your proposed
PreparedStatementCreatorTemplateProcessor
is too much boilerplate for your codebase?
For our code base no. We already have quite a bit of custom JDBC support code and that will fit right in. But I do think it's not ideal when this snipped has to be copy an pasted in a lot of projects, especially with your improvement to TYPE_UNKNOWN
.
Comment From: simonbasle
One thing we could do to anticipate support is provide code from that process
method as a static utility method, albeit with a different signature which doesn't involve StringTemplate
but is easy enough to adapt...
But still, I'm not keen on providing something based on a Preview Feature. Sure, it's not Experimental but depending on community feedback things could still change.
So I'm inclined to close this one for now. Would you be willing to reopen an issue when String Template feature is officially released in Java @marschall ?
Comment From: marschall
So I'm inclined to close this one for now. Would you be willing to reopen an issue when String Template feature is officially released in Java @marschall ?
Sure
Comment From: simonbasle
This will need to be revisited once the String Template feature is GA in Java, at which point there should be a way for Spring to provide supporting methods to reduce the boilerplate in creating a StringTemplate.Processor
(or even provide such a processor depending on the java baseline at the time).
Comment From: snicoll
We could also reuse this issue with a ping to ask us to reconsider.