Description
Version with problems:
SpringBoot 2.6.2, 2.5.4 or above, 2.3.10.RELEASE or above
SpringDataMongoDB 3.3.0 3.2.4 or above, 3.0.8.RELEASE or above
these are the versions I test, maybe not very accurate, but the infomation may make some effect
Brief introduction
Just as the title says, MongoTemplate.UpdateFirst just went wrong and break the document structure
How to reproduce
I just past my code, the test method and data classes in one class:
package com.example.mongotest.test;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
@Component
public class Tester {
private final MongoTemplate mongoTemplate;
public Tester(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
@PostConstruct
public void test() {
TestValue testValue = new TestValue();
testValue.setIntValue(1);
Map<Integer, TestValue> testMap = new HashMap<>(16);
testMap.put(1, testValue);
TestInnerData testInnerData = new TestInnerData();
testInnerData.setTestMap(testMap);
TestData testData = new TestData();
testData.setId("2");
testData.setTestInnerData(testInnerData);
mongoTemplate.save(testData);
mongoTemplate.updateFirst(
Query.query(Criteria.where("_id").is("2")),
Update.update("testInnerData.testMap.1.intValue", 2),
TestData.class
);
mongoTemplate.updateFirst(
Query.query(Criteria.where("_id").is("2")),
Update.update("testInnerData.testMap.1.intValue", 3),
TestData.class
);
}
@Document
private static class TestData {
@Id
private String id;
private TestInnerData testInnerData;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public TestInnerData getTestInnerData() {
return testInnerData;
}
public void setTestInnerData(TestInnerData testInnerData) {
this.testInnerData = testInnerData;
}
}
private static class TestInnerData {
private Map<Integer, TestValue> testMap;
public Map<Integer, TestValue> getTestMap() {
return testMap;
}
public void setTestMap(Map<Integer, TestValue> testMap) {
this.testMap = testMap;
}
}
private static class TestValue {
private int intValue;
public int getIntValue() {
return intValue;
}
public void setIntValue(int intValue) {
this.intValue = intValue;
}
}
}
The result in MongoDB with SpringBoot2.6.2(or 2.5.X, X), SpringDataMongoDB3.3.0:
{
_id: '2',
testInnerData: { testMap: { '1': { intValue: 1 }, intValue: { intValue: 3 } } },
_class: 'com.example.mongotest.test.Tester$TestData'
}
Change SpringBoot version to 2.3.9.RELEASE(SpringDataMongoDB 3.0.7.RELEASE), we get the expected result:
{
_id: '2',
testInnerData: { testMap: { '1': { intValue: 3 } } },
_class: 'com.example.mongotest.test.Tester$TestData'
}
As the result shows, we get wrong result with springboot2.6.2, I don't know this has some relation with #3689 or #3775 , in issue #3689 similar numeric key bug happens, but marked as resolved and backported to Spring Data MongoDB3.2.X. So with the infomation above, hope you can figure out what goes wrong, if this is not a bug but my mistake in using SpringDataMongoDB, I'm sorry for my interrupt.