Skip to content

Commit c4f9369

Browse files
christophstroblmp911de
authored andcommitted
Polishing.
Update tests to work with new defaults and move those with previous String defaulting into a new home. Revise reference documentation. Original pull request: #4957 See: #4920
1 parent 71715dc commit c4f9369

File tree

7 files changed

+221
-55
lines changed

7 files changed

+221
-55
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoCustomConversions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ public MongoConverterConfigurationAdapter useSpringDataJavaTimeCodecs() {
314314

315315
/**
316316
* Configures the representation to for {@link java.math.BigDecimal} and {@link java.math.BigInteger} values in
317-
* MongoDB. Defaults to {@link BigDecimalRepresentation#STRING}.
317+
* MongoDB. Defaults to {@link BigDecimalRepresentation#DECIMAL128}.
318318
*
319319
* @param representation the representation to use.
320320
* @return this.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
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 org.springframework.data.mongodb.core;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.springframework.data.mongodb.core.query.Criteria.where;
20+
import static org.springframework.data.mongodb.core.query.Query.query;
21+
22+
import java.math.BigDecimal;
23+
import java.math.BigInteger;
24+
import java.util.List;
25+
26+
import org.junit.jupiter.api.AfterEach;
27+
import org.junit.jupiter.api.Test;
28+
import org.junit.jupiter.api.extension.ExtendWith;
29+
import org.springframework.data.auditing.IsNewAwareAuditingHandler;
30+
import org.springframework.data.mapping.context.PersistentEntities;
31+
import org.springframework.data.mongodb.core.MongoTemplateTests.TypeWithNumbers;
32+
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
33+
import org.springframework.data.mongodb.core.convert.MongoCustomConversions.BigDecimalRepresentation;
34+
import org.springframework.data.mongodb.core.query.Criteria;
35+
import org.springframework.data.mongodb.core.query.Query;
36+
import org.springframework.data.mongodb.core.query.Update;
37+
import org.springframework.data.mongodb.test.util.Client;
38+
import org.springframework.data.mongodb.test.util.MongoClientExtension;
39+
import org.springframework.data.mongodb.test.util.MongoTestTemplate;
40+
41+
import com.mongodb.client.MongoClient;
42+
43+
/**
44+
* Tests for {@link MongoTemplate} using string representation of {@link BigInteger} values.
45+
*
46+
* @author Christoph Strobl
47+
*/
48+
@ExtendWith(MongoClientExtension.class)
49+
public class BigDecimalToStringConvertingTemplateTests {
50+
51+
public static final String DB_NAME = "mongo-template-tests";
52+
53+
static @Client MongoClient client;
54+
55+
@SuppressWarnings("deprecation") MongoTestTemplate template = new MongoTestTemplate(cfg -> {
56+
57+
cfg.configureDatabaseFactory(it -> {
58+
59+
it.client(client);
60+
it.defaultDb(DB_NAME);
61+
});
62+
63+
cfg.configureConversion(it -> {
64+
it.customConversions(
65+
MongoCustomConversions.create(adapter -> adapter.bigDecimal(BigDecimalRepresentation.STRING)));
66+
});
67+
68+
cfg.configureMappingContext(it -> {
69+
it.autocreateIndex(false);
70+
});
71+
72+
cfg.configureAuditing(it -> {
73+
it.auditingHandler(ctx -> {
74+
return new IsNewAwareAuditingHandler(PersistentEntities.of(ctx));
75+
});
76+
});
77+
});
78+
79+
@AfterEach
80+
public void cleanUp() {
81+
template.flush();
82+
}
83+
84+
@Test // DATAMONGO-602
85+
void testUsingAnInQueryWithBigIntegerId() {
86+
87+
template.remove(new Query(), PersonWithIdPropertyOfTypeBigInteger.class);
88+
89+
PersonWithIdPropertyOfTypeBigInteger p1 = new PersonWithIdPropertyOfTypeBigInteger();
90+
p1.setFirstName("Sven");
91+
p1.setAge(11);
92+
p1.setId(new BigInteger("2666666666666666665069473312490162649510603601"));
93+
template.insert(p1);
94+
PersonWithIdPropertyOfTypeBigInteger p2 = new PersonWithIdPropertyOfTypeBigInteger();
95+
p2.setFirstName("Mary");
96+
p2.setAge(21);
97+
p2.setId(new BigInteger("2666666666666666665069473312490162649510603602"));
98+
template.insert(p2);
99+
PersonWithIdPropertyOfTypeBigInteger p3 = new PersonWithIdPropertyOfTypeBigInteger();
100+
p3.setFirstName("Ann");
101+
p3.setAge(31);
102+
p3.setId(new BigInteger("2666666666666666665069473312490162649510603603"));
103+
template.insert(p3);
104+
PersonWithIdPropertyOfTypeBigInteger p4 = new PersonWithIdPropertyOfTypeBigInteger();
105+
p4.setFirstName("John");
106+
p4.setAge(41);
107+
p4.setId(new BigInteger("2666666666666666665069473312490162649510603604"));
108+
template.insert(p4);
109+
110+
Query q1 = new Query(Criteria.where("age").in(11, 21, 41));
111+
List<PersonWithIdPropertyOfTypeBigInteger> results1 = template.find(q1, PersonWithIdPropertyOfTypeBigInteger.class);
112+
Query q2 = new Query(Criteria.where("firstName").in("Ann", "Mary"));
113+
List<PersonWithIdPropertyOfTypeBigInteger> results2 = template.find(q2, PersonWithIdPropertyOfTypeBigInteger.class);
114+
Query q3 = new Query(Criteria.where("id").in(new BigInteger("2666666666666666665069473312490162649510603601"),
115+
new BigInteger("2666666666666666665069473312490162649510603604")));
116+
List<PersonWithIdPropertyOfTypeBigInteger> results3 = template.find(q3, PersonWithIdPropertyOfTypeBigInteger.class);
117+
assertThat(results1.size()).isEqualTo(3);
118+
assertThat(results2.size()).isEqualTo(2);
119+
assertThat(results3.size()).isEqualTo(2);
120+
}
121+
122+
@Test // DATAMONGO-1404
123+
void updatesBigNumberValueUsingStringComparisonWhenUsingMaxOperator() {
124+
125+
TypeWithNumbers twn = new TypeWithNumbers();
126+
127+
// Note that $max operator uses String comparison for BigDecimal/BigInteger comparison according to BSON sort rules.
128+
// Therefore "80" is considered greater than "700"
129+
twn.bigIntegerVal = new BigInteger("600");
130+
twn.bigDeciamVal = new BigDecimal("700.0");
131+
132+
template.save(twn);
133+
134+
Update update = new Update()//
135+
.max("bigIntegerVal", new BigInteger("70")) //
136+
.max("bigDeciamVal", new BigDecimal("80")) //
137+
;
138+
139+
template.updateFirst(query(where("id").is(twn.id)), update, TypeWithNumbers.class);
140+
141+
TypeWithNumbers loaded = template.find(query(where("id").is(twn.id)), TypeWithNumbers.class).get(0);
142+
assertThat(loaded.bigIntegerVal).isEqualTo(new BigInteger("70"));
143+
assertThat(loaded.bigDeciamVal).isEqualTo(new BigDecimal("80"));
144+
}
145+
146+
@Test // DATAMONGO-1404
147+
void updatesBigNumberValueUsingStringComparisonWhenUsingMinOperator() {
148+
149+
TypeWithNumbers twn = new TypeWithNumbers();
150+
151+
// Note that $max operator uses String comparison for BigDecimal/BigInteger comparison according to BSON sort rules.
152+
// Therefore "80" is considered greater than "700"
153+
twn.bigIntegerVal = new BigInteger("80");
154+
twn.bigDeciamVal = new BigDecimal("90.0");
155+
156+
template.save(twn);
157+
158+
Update update = new Update()//
159+
.min("bigIntegerVal", new BigInteger("700")) //
160+
.min("bigDeciamVal", new BigDecimal("800")) //
161+
;
162+
163+
template.updateFirst(query(where("id").is(twn.id)), update, TypeWithNumbers.class);
164+
165+
TypeWithNumbers loaded = template.find(query(where("id").is(twn.id)), TypeWithNumbers.class).get(0);
166+
assertThat(loaded.bigIntegerVal).isEqualTo(new BigInteger("700"));
167+
assertThat(loaded.bigDeciamVal).isEqualTo(new BigDecimal("800"));
168+
}
169+
170+
}

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java

Lines changed: 11 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
import org.springframework.context.ConfigurableApplicationContext;
4343
import org.springframework.context.support.GenericApplicationContext;
44+
import org.springframework.core.convert.ConversionFailedException;
4445
import org.springframework.core.convert.converter.Converter;
4546
import org.springframework.dao.DataAccessException;
4647
import org.springframework.dao.DataIntegrityViolationException;
@@ -874,7 +875,7 @@ public void testUsingAnInQueryWithLongId() throws Exception {
874875
assertThat(results3.size()).isEqualTo(2);
875876
}
876877

877-
@Test // DATAMONGO-602
878+
@Test // DATAMONGO-602, GH-4920
878879
public void testUsingAnInQueryWithBigIntegerId() throws Exception {
879880

880881
template.remove(new Query(), PersonWithIdPropertyOfTypeBigInteger.class);
@@ -883,33 +884,7 @@ public void testUsingAnInQueryWithBigIntegerId() throws Exception {
883884
p1.setFirstName("Sven");
884885
p1.setAge(11);
885886
p1.setId(new BigInteger("2666666666666666665069473312490162649510603601"));
886-
template.insert(p1);
887-
PersonWithIdPropertyOfTypeBigInteger p2 = new PersonWithIdPropertyOfTypeBigInteger();
888-
p2.setFirstName("Mary");
889-
p2.setAge(21);
890-
p2.setId(new BigInteger("2666666666666666665069473312490162649510603602"));
891-
template.insert(p2);
892-
PersonWithIdPropertyOfTypeBigInteger p3 = new PersonWithIdPropertyOfTypeBigInteger();
893-
p3.setFirstName("Ann");
894-
p3.setAge(31);
895-
p3.setId(new BigInteger("2666666666666666665069473312490162649510603603"));
896-
template.insert(p3);
897-
PersonWithIdPropertyOfTypeBigInteger p4 = new PersonWithIdPropertyOfTypeBigInteger();
898-
p4.setFirstName("John");
899-
p4.setAge(41);
900-
p4.setId(new BigInteger("2666666666666666665069473312490162649510603604"));
901-
template.insert(p4);
902-
903-
Query q1 = new Query(Criteria.where("age").in(11, 21, 41));
904-
List<PersonWithIdPropertyOfTypeBigInteger> results1 = template.find(q1, PersonWithIdPropertyOfTypeBigInteger.class);
905-
Query q2 = new Query(Criteria.where("firstName").in("Ann", "Mary"));
906-
List<PersonWithIdPropertyOfTypeBigInteger> results2 = template.find(q2, PersonWithIdPropertyOfTypeBigInteger.class);
907-
Query q3 = new Query(Criteria.where("id").in(new BigInteger("2666666666666666665069473312490162649510603601"),
908-
new BigInteger("2666666666666666665069473312490162649510603604")));
909-
List<PersonWithIdPropertyOfTypeBigInteger> results3 = template.find(q3, PersonWithIdPropertyOfTypeBigInteger.class);
910-
assertThat(results1.size()).isEqualTo(3);
911-
assertThat(results2.size()).isEqualTo(2);
912-
assertThat(results3.size()).isEqualTo(2);
887+
assertThatExceptionOfType(ConversionFailedException.class).isThrownBy(() -> template.insert(p1));
913888
}
914889

915890
@Test
@@ -3274,7 +3249,6 @@ public void updatesNumericValueCorrectlyWhenUsingMinOperator() {
32743249
twn.intVal = 400;
32753250
twn.longVal = 500L;
32763251

3277-
// Note that $min operator uses String comparison for BigDecimal/BigInteger comparison according to BSON sort rules.
32783252
twn.bigIntegerVal = new BigInteger("600");
32793253
twn.bigDeciamVal = new BigDecimal("700.0");
32803254

@@ -3330,7 +3304,6 @@ public void updatesNumericValueCorrectlyWhenUsingMaxOperator() {
33303304
twn.intVal = 400;
33313305
twn.longVal = 500L;
33323306

3333-
// Note that $max operator uses String comparison for BigDecimal/BigInteger comparison according to BSON sort rules.
33343307
twn.bigIntegerVal = new BigInteger("600");
33353308
twn.bigDeciamVal = new BigDecimal("700.0");
33363309

@@ -3359,13 +3332,11 @@ public void updatesNumericValueCorrectlyWhenUsingMaxOperator() {
33593332
assertThat(loaded.bigDeciamVal).isEqualTo(new BigDecimal("790"));
33603333
}
33613334

3362-
@Test // DATAMONGO-1404
3363-
public void updatesBigNumberValueUsingStringComparisonWhenUsingMaxOperator() {
3335+
@Test // DATAMONGO-1404, GH-4920
3336+
public void updatesBigNumberValueUsingUsingMaxOperator() {
33643337

33653338
TypeWithNumbers twn = new TypeWithNumbers();
33663339

3367-
// Note that $max operator uses String comparison for BigDecimal/BigInteger comparison according to BSON sort rules.
3368-
// Therefore "80" is considered greater than "700"
33693340
twn.bigIntegerVal = new BigInteger("600");
33703341
twn.bigDeciamVal = new BigDecimal("700.0");
33713342

@@ -3379,17 +3350,15 @@ public void updatesBigNumberValueUsingStringComparisonWhenUsingMaxOperator() {
33793350
template.updateFirst(query(where("id").is(twn.id)), update, TypeWithNumbers.class);
33803351

33813352
TypeWithNumbers loaded = template.find(query(where("id").is(twn.id)), TypeWithNumbers.class).get(0);
3382-
assertThat(loaded.bigIntegerVal).isEqualTo(new BigInteger("70"));
3383-
assertThat(loaded.bigDeciamVal).isEqualTo(new BigDecimal("80"));
3353+
assertThat(loaded.bigIntegerVal).isEqualTo(new BigInteger("600"));
3354+
assertThat(loaded.bigDeciamVal).isEqualTo(new BigDecimal("700.0"));
33843355
}
33853356

3386-
@Test // DATAMONGO-1404
3387-
public void updatesBigNumberValueUsingStringComparisonWhenUsingMinOperator() {
3357+
@Test // DATAMONGO-1404, GH-4920
3358+
public void updatesBigNumberValueWhenUsingMinOperator() {
33883359

33893360
TypeWithNumbers twn = new TypeWithNumbers();
33903361

3391-
// Note that $max operator uses String comparison for BigDecimal/BigInteger comparison according to BSON sort rules.
3392-
// Therefore "80" is considered greater than "700"
33933362
twn.bigIntegerVal = new BigInteger("80");
33943363
twn.bigDeciamVal = new BigDecimal("90.0");
33953364

@@ -3403,8 +3372,8 @@ public void updatesBigNumberValueUsingStringComparisonWhenUsingMinOperator() {
34033372
template.updateFirst(query(where("id").is(twn.id)), update, TypeWithNumbers.class);
34043373

34053374
TypeWithNumbers loaded = template.find(query(where("id").is(twn.id)), TypeWithNumbers.class).get(0);
3406-
assertThat(loaded.bigIntegerVal).isEqualTo(new BigInteger("700"));
3407-
assertThat(loaded.bigDeciamVal).isEqualTo(new BigDecimal("800"));
3375+
assertThat(loaded.bigIntegerVal).isEqualTo(new BigInteger("80"));
3376+
assertThat(loaded.bigDeciamVal).isEqualTo(new BigDecimal("90.0"));
34083377
}
34093378

34103379
@Test // DATAMONGO-1431, DATAMONGO-2323

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,9 @@ void setUp() {
8989
this.dbRefResolver = spy(new DefaultDbRefResolver(dbFactory));
9090
this.mappingContext = new MongoMappingContext();
9191
this.mappingContext.setSimpleTypeHolder(new MongoCustomConversions(Collections.emptyList()).getSimpleTypeHolder());
92+
this.mappingContext.afterPropertiesSet();
9293
this.converter = new MappingMongoConverter(dbRefResolver, mappingContext);
94+
this.converter.afterPropertiesSet();
9395
}
9496

9597
@Test // DATAMONGO-347
@@ -103,7 +105,7 @@ void createsSimpleDBRefCorrectly() {
103105
assertThat(dbRef.getCollectionName()).isEqualTo("person");
104106
}
105107

106-
@Test // DATAMONGO-657
108+
@Test // DATAMONGO-657, GH-4920
107109
void convertDocumentWithMapDBRef() {
108110

109111
Document mapValDocument = new Document();
@@ -610,7 +612,7 @@ void shouldFallbackToOneByOneFetchingWhenElementsInListOfReferencesPointToDiffer
610612
verify(converterSpy, never()).bulkReadRefs(anyList());
611613
}
612614

613-
@Test // DATAMONGO-1194
615+
@Test // DATAMONGO-1194, GH-4920
614616
void shouldBulkFetchMapOfReferences() {
615617

616618
MapDBRefVal val1 = new MapDBRefVal();
@@ -642,7 +644,7 @@ void shouldBulkFetchMapOfReferences() {
642644
verify(converterSpy, never()).readRef(Mockito.any(DBRef.class));
643645
}
644646

645-
@Test // DATAMONGO-1194
647+
@Test // DATAMONGO-1194, GH-4920
646648
void shouldBulkFetchLazyMapOfReferences() {
647649

648650
MapDBRefVal val1 = new MapDBRefVal();

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ void readsNestedMapsCorrectly() {
384384
assertThat(nestedMap.get("afield")).isEqualTo(firstLevel);
385385
}
386386

387-
@Test // DATACMNS-42, DATAMONGO-171
387+
@Test // DATACMNS-42, DATAMONGO-171, GH-4920
388388
void writesClassWithBigDecimal() {
389389

390390
BigDecimalContainer container = new BigDecimalContainer();
@@ -394,9 +394,8 @@ void writesClassWithBigDecimal() {
394394
org.bson.Document document = new org.bson.Document();
395395
converter.write(container, document);
396396

397-
assertThat(document.get("value")).isInstanceOf(String.class);
398-
assertThat((String) document.get("value")).isEqualTo("2.5");
399-
assertThat(((org.bson.Document) document.get("map")).get("foo")).isInstanceOf(String.class);
397+
assertThat(document.get("value")).isEqualTo(Decimal128.parse("2.5"));
398+
assertThat(((org.bson.Document) document.get("map")).get("foo")).isInstanceOf(Decimal128.class);
400399
}
401400

402401
@Test // DATACMNS-42, DATAMONGO-171
@@ -513,7 +512,7 @@ void writesNullValuesForMaps() {
513512
assertThat(((org.bson.Document) map).keySet()).contains("en_US");
514513
}
515514

516-
@Test
515+
@Test // GH-4920
517516
void writesBigIntegerIdCorrectly() {
518517

519518
ClassWithBigIntegerId foo = new ClassWithBigIntegerId();
@@ -522,7 +521,7 @@ void writesBigIntegerIdCorrectly() {
522521
org.bson.Document result = new org.bson.Document();
523522
converter.write(foo, result);
524523

525-
assertThat(result.get("_id")).isInstanceOf(String.class);
524+
assertThat(result.get("_id")).isInstanceOf(Decimal128.class);
526525
}
527526

528527
@Test

0 commit comments

Comments
 (0)