- 
                Notifications
    You must be signed in to change notification settings 
- Fork 38.8k
Closed as not planned
Closed as not planned
Copy link
Labels
in: dataIssues in data modules (jdbc, orm, oxm, tx)Issues in data modules (jdbc, orm, oxm, tx)status: invalidAn issue that we don't feel is validAn issue that we don't feel is valid
Description
I'm using the latest Spring boot 3.4.1.
How to reproduce bug:
- Create table in database:
   @PostConstruct
   public void createTable() {
       final String sql = "CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name VARCHAR(255), company " +
               "VARCHAR(255))";
       jdbcTemplate.execute(sql);
   }
- Use NamedParameterJdbcOperations for bulk update with this kinda query:
    public void incorrectBulkUpdate(Map<String, List<String>> info) {
        final String sql = "UPDATE users SET company = :company WHERE name IN (:names)";
        SqlParameterSource[] params = info.entrySet().stream()
                .sorted((e1, e2) -> Integer.compare(e1.getValue().size(), e2.getValue().size())) // pay attention to this line!!!
                .map(e -> new MapSqlParameterSource()
                        .addValue("company", e.getKey())
                        .addValue("names", e.getValue())
                )
                .toArray(SqlParameterSource[]::new);
        jdbcOperations.batchUpdate(sql, params);
    }
In general I want to use bulk update with one of query arguments is a collection (in this example argument :names is a list).
Also I sorted parameters with increasing size order of :names argument.
3) Try to execute it with different sized :names argument, for example:
	@Transactional
	@Test
	void incorrectBulkUpdateTest() {
		simpleService.add("John", "google");
		simpleService.add("Nick", "facebook");
		simpleService.add("Anna", "netflix");
		var found = simpleService.findByName("John");
		assertEquals(1, found.size());
		assertEquals("google", found.get(0).company);
		simpleService.incorrectBulkUpdate(
				Map.of(
						"amazon", List.of("Nick", "Anna"),
						"tesla", List.of("John")
				)
		);
		found = simpleService.findByName("John");
		assertEquals(1, found.size());
		assertEquals("tesla", found.get(0).company);
	}
And got something like:
org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [UPDATE users SET company = ? WHERE name IN (?)]; The column index is out of range: 3, number of columns: 2.
But there is a twist.
If I sort arguments in decreasing order, like
.sorted((e1, e2) -> -Integer.compare(e1.getValue().size(), e2.getValue().size()))
everything is fine and test is successful.
I think there is some bug in SQL processing, when query with named parameters is transformed into a query with question marks.
You can see full example in repo: https://github.com/koalaa13/SpringBootIssueExample
Thank you in advance!
Alesiks and nkey0
Metadata
Metadata
Assignees
Labels
in: dataIssues in data modules (jdbc, orm, oxm, tx)Issues in data modules (jdbc, orm, oxm, tx)status: invalidAn issue that we don't feel is validAn issue that we don't feel is valid