-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Closed
Description
Description
When using Spring Data MongoDB with entities annotated with @MongoId String id, there is an inconsistency in how the _id field is stored in MongoDB depending on whether save or saveAll is used. Specifically, save stores the _id as a String, while saveAll stores it as an ObjectId, even though the ID is not explicitly set in either case.
That even leads to duplication in the DB, since when used saveAll and the update it will convert it to string but creates a duplicated object
Steps to Reproduce
- Set up a Spring Boot project with the following dependencies:
- Spring Boot Starter Data MongoDB
- Run the application and observe the output.
- Check the DB
package com.example.mongo_bug;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.MongoId;
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.List;
@SpringBootApplication
public class MongoBugApplication {
public static void main(String[] args) {
SpringApplication.run(MongoBugApplication.class, args);
}
@Bean
public CommandLineRunner commandLineRunner(MyRepository repository) {
return args -> {
// Create entities without setting ID
MyEntity entity1 = new MyEntity();
entity1.setName("Entity1");
MyEntity entity2 = new MyEntity();
entity2.setName("Entity2");
// Save using save
repository.save(entity1);
// Save using saveAll
repository.saveAll(List.of(entity2));
// Update the name of entity2 will lead to duplicate
entity2.setName("UpdatedEntity2");
repository.save(entity2);
// Find all entities
List<MyEntity> allEntities = repository.findAll();
allEntities.forEach(entity -> System.out.println("Entity ID: " + entity.getId() + ", Name: " + entity.getName()));
};
}
}
// Repository interface
interface MyRepository extends MongoRepository<MyEntity, String> {
}
// Entity class
@Document
class MyEntity {
@MongoId
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Expected Behavior
- Both
saveandsaveAllstore_idas a String in MongoDB whenidisnulland the field isString.
Actual Behavior
savestores_idas aString.saveAllstores _id as anObjectId.- Updating an entity saved with
saveAllcreates a duplicate due to the type mismatch.
{
_id: '67f82b6888d11c0743a9097f',
name: 'Entity1',
_class: 'com.example.mongo_bug.MyEntity'
}
{
_id: ObjectId("67f82b6888d11c0743a90980"),
name: 'Entity2',
_class: 'com.example.mongo_bug.MyEntity'
}
{
_id: '67f82b6888d11c0743a90980',
name: 'UpdatedEntity2',
_class: 'com.example.mongo_bug.MyEntity'
}
Environment
- Spring Boot Version: 3.4.4
- Spring Data MongoDB Version: 4.4.4
- MongoDB Version: 8.0.6
- Java Version: temurin-22.0.2
- Operating System: Ubuntu 24.04.2 LTS
Test Project To Reproduce
Metadata
Metadata
Assignees
Labels
type: bugA general bugA general bug
