Skip to content

Commit c35867e

Browse files
christophstroblmp911de
authored andcommitted
Add MongoDB Bulk Write sample.
1 parent b87653f commit c35867e

14 files changed

Lines changed: 221 additions & 9 deletions

File tree

README.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ Contains also examples running on Virtual Threads.
6060

6161
* `aot-optimization` - Use Ahead-Of-Time Repositories with Spring Data MongoDB.
6262
* `aggregation` - Example project to showcase the MongoDB aggregation framework support.
63-
* `example` - Example project for general repository functionality (including geo-spatial functionality), Querydsl integration and advanced topics.
63+
* `example` - Example project for general repository functionality (including geo-spatial functionality), Querydsl integration, bulk write and other advanced topics.
6464
* `fluent-api` - Example project to show the new fluent API (`MongoTemplate`-alternative) to interact with MongoDB.
6565
* `geo-json` - Example project showing usage of http://geojson.org[GeoJSON] with MongoDB.
6666
* `gridfs` - Example project showing usage of gridFS with MongoDB.

jdbc/immutables/src/main/java/example/springdata/jdbc/immutables/Application.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.springframework.context.annotation.Configuration;
2020
import org.springframework.context.annotation.Lazy;
2121
import org.springframework.core.io.ResourceLoader;
22+
import org.springframework.data.core.TypeInformation;
2223
import org.springframework.data.jdbc.core.convert.DefaultJdbcTypeFactory;
2324
import org.springframework.data.jdbc.core.convert.JdbcConverter;
2425
import org.springframework.data.jdbc.core.convert.JdbcCustomConversions;
@@ -29,7 +30,6 @@
2930
import org.springframework.data.relational.core.conversion.RowDocumentAccessor;
3031
import org.springframework.data.relational.core.dialect.Dialect;
3132
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
32-
import org.springframework.data.util.TypeInformation;
3333
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
3434
import org.springframework.util.ClassUtils;
3535

@@ -67,7 +67,7 @@ public ImmutablesJdbcConfiguration(ResourceLoader resourceLoader) {
6767
* @param dialect
6868
* @return
6969
*/
70-
@Override
70+
// @Override
7171
public JdbcConverter jdbcConverter(JdbcMappingContext mappingContext, NamedParameterJdbcOperations operations,
7272
@Lazy RelationResolver relationResolver, JdbcCustomConversions conversions, Dialect dialect) {
7373

mongodb/example/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ This project contains examples for:
66
* Usage of property-specific converters.
77
* `EntityCallback` API usage for before convert/save interaction.
88
* Result projections for DTOs and interface types.
9+
* Bulk write to multiple collections.
910
* Query metadata.
1011
* Unwrapping entities into the parent document.
1112

mongodb/example/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@
4949
<groupId>com.fasterxml.jackson.core</groupId>
5050
<artifactId>jackson-databind</artifactId>
5151
</dependency>
52+
<dependency>
53+
<groupId>org.springframework</groupId>
54+
<artifactId>spring-core</artifactId>
55+
<version>7.0.3</version>
56+
</dependency>
5257
<dependency>
5358
<groupId>org.springframework.data.examples</groupId>
5459
<artifactId>spring-data-mongodb-example-utils</artifactId>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2026-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.mongodb.bulk;
17+
18+
import org.springframework.boot.autoconfigure.SpringBootApplication;
19+
20+
/**
21+
* Configuration for bulk write example tests.
22+
*
23+
* @author Christoph Strobl
24+
*/
25+
@SpringBootApplication
26+
class ApplicationConfiguration {
27+
28+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright 2026-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.mongodb.bulk;
17+
18+
import org.springframework.data.mongodb.core.mapping.Document;
19+
20+
/**
21+
* Domain type for bulk write examples, using Star Wars character names.
22+
*
23+
* @author Christoph Strobl
24+
*/
25+
@Document
26+
public class Jedi {
27+
28+
private String id;
29+
private String firstname;
30+
private String lastname;
31+
32+
public Jedi(String firstname, String lastname) {
33+
34+
this.firstname = firstname;
35+
this.lastname = lastname;
36+
}
37+
38+
public String getId() {
39+
return id;
40+
}
41+
42+
public void setId(String id) {
43+
this.id = id;
44+
}
45+
46+
public String getFirstname() {
47+
return firstname;
48+
}
49+
50+
public void setFirstname(String firstname) {
51+
this.firstname = firstname;
52+
}
53+
54+
public String getLastname() {
55+
return lastname;
56+
}
57+
58+
public void setLastname(String lastname) {
59+
this.lastname = lastname;
60+
}
61+
62+
public String fullName() {
63+
return firstname + " " + lastname;
64+
}
65+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2026-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.mongodb.bulk;
17+
18+
import org.springframework.data.annotation.Id;
19+
20+
/**
21+
* @author Christoph Strobl
22+
*/
23+
public record Sith(@Id String name, String realName) {
24+
25+
}

mongodb/example/src/test/java/example/springdata/mongodb/advanced/AdvancedIntegrationTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class AdvancedIntegrationTests {
5151

5252
@DynamicPropertySource
5353
static void setProperties(DynamicPropertyRegistry registry) {
54-
registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
54+
registry.add("spring.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
5555
}
5656

5757
@Autowired AdvancedRepository repository;
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.mongodb.bulk;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.springframework.data.mongodb.core.query.Criteria.where;
20+
21+
import example.springdata.mongodb.util.MongoContainers;
22+
import org.junit.jupiter.api.BeforeEach;
23+
import org.junit.jupiter.api.Test;
24+
import org.springframework.beans.factory.annotation.Autowired;
25+
import org.springframework.boot.data.mongodb.test.autoconfigure.DataMongoTest;
26+
import org.springframework.data.mongodb.core.MongoOperations;
27+
import org.springframework.data.mongodb.core.bulk.Bulk;
28+
import org.springframework.data.mongodb.core.bulk.BulkWriteOptions;
29+
import org.springframework.data.mongodb.core.bulk.BulkWriteResult;
30+
import org.springframework.data.mongodb.core.query.Update;
31+
import org.springframework.test.context.DynamicPropertyRegistry;
32+
import org.springframework.test.context.DynamicPropertySource;
33+
import org.testcontainers.junit.jupiter.Container;
34+
import org.testcontainers.junit.jupiter.Testcontainers;
35+
import org.testcontainers.mongodb.MongoDBContainer;
36+
37+
/**
38+
* Integration test demonstrating {@link MongoOperations#bulkWrite(Bulk, BulkWriteOptions)} with a combination of
39+
* insert and update operations in a single request.
40+
*
41+
* @author Christoph Strobl
42+
*/
43+
@Testcontainers
44+
@DataMongoTest
45+
class BulkWriteIntegrationTest {
46+
47+
@Container
48+
private static MongoDBContainer mongoDBContainer = MongoContainers.getDefaultContainer();
49+
50+
@DynamicPropertySource
51+
static void setProperties(DynamicPropertyRegistry registry) {
52+
registry.add("spring.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
53+
}
54+
55+
@Autowired
56+
MongoOperations operations;
57+
58+
@BeforeEach
59+
void setUp() {
60+
operations.dropCollection(Jedi.class);
61+
}
62+
63+
@Test
64+
void bulkWriteInsertAndUpdateInOrder() {
65+
66+
Bulk bulk = Bulk.create(builder -> builder.inCollection(Jedi.class, spec -> spec
67+
.insert(new Jedi("Luke", "Skywalker"))
68+
.insert(new Jedi("Leia", "Princess"))
69+
.updateOne(where("firstname").is("Leia"), new Update().set("lastname", "Organa")))
70+
.inCollection(Sith.class, spec -> spec.upsert(where("name").is("Darth Sidious"), Update.update("realName", "Palpatine")))
71+
);
72+
73+
BulkWriteResult result = operations.bulkWrite(bulk, BulkWriteOptions.ordered());
74+
75+
assertThat(result.acknowledged()).isTrue();
76+
assertThat(result.insertCount()).isEqualTo(2); // luke & leia
77+
assertThat(result.modifiedCount()).isOne(); // leia
78+
assertThat(result.upsertCount()).isOne(); // darth sidious
79+
80+
assertThat(operations.findAll(Jedi.class))
81+
.extracting(Jedi::fullName)
82+
.containsExactlyInAnyOrder("Luke Skywalker", "Leia Organa");
83+
84+
assertThat(operations.findAll(Sith.class))
85+
.extracting(Sith::name)
86+
.containsExactlyInAnyOrder("Darth Sidious");
87+
}
88+
}

mongodb/example/src/test/java/example/springdata/mongodb/converters/CustomerIntegrationTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class CustomerIntegrationTests {
4949

5050
@DynamicPropertySource
5151
static void setProperties(DynamicPropertyRegistry registry) {
52-
registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
52+
registry.add("spring.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
5353
}
5454

5555
@Autowired MongoOperations operations;

0 commit comments

Comments
 (0)