Skip to content

Set value of Map with numeric key breaks data structure #3921

Closed
@derekxia1988

Description

@derekxia1988

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.

Metadata

Metadata

Labels

type: regressionA regression from a previous release

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions