15
15
*/
16
16
package org .springframework .data .mongodb .core ;
17
17
18
- import static org .assertj .core .api .Assertions .*;
19
- import static org .springframework .data .mongodb .core .query .Criteria .*;
20
- import static org .springframework .data .mongodb .core .query .Query .*;
21
- import static org .springframework .data .mongodb .core .query .Update .*;
18
+ import static org .assertj .core .api .Assertions .assertThat ;
19
+ import static org .assertj .core .api .Assertions .assertThatExceptionOfType ;
20
+ import static org .assertj .core .api .Assertions .assertThatIllegalArgumentException ;
21
+ import static org .assertj .core .api .Assertions .fail ;
22
+ import static org .springframework .data .mongodb .core .query .Criteria .expr ;
23
+ import static org .springframework .data .mongodb .core .query .Criteria .where ;
24
+ import static org .springframework .data .mongodb .core .query .Query .query ;
25
+ import static org .springframework .data .mongodb .core .query .Update .update ;
22
26
23
27
import java .lang .reflect .InvocationTargetException ;
24
28
import java .math .BigDecimal ;
28
32
import java .time .LocalDateTime ;
29
33
import java .time .ZoneId ;
30
34
import java .time .temporal .ChronoUnit ;
31
- import java .util .*;
35
+ import java .util .ArrayList ;
36
+ import java .util .Arrays ;
37
+ import java .util .Calendar ;
38
+ import java .util .Collections ;
39
+ import java .util .Date ;
40
+ import java .util .HashMap ;
41
+ import java .util .Iterator ;
42
+ import java .util .LinkedHashMap ;
43
+ import java .util .List ;
44
+ import java .util .Locale ;
45
+ import java .util .Map ;
46
+ import java .util .Objects ;
47
+ import java .util .UUID ;
32
48
import java .util .concurrent .atomic .AtomicReference ;
33
49
import java .util .stream .Collectors ;
34
50
import java .util .stream .IntStream ;
35
51
import java .util .stream .Stream ;
36
52
53
+ import org .bson .codecs .configuration .CodecConfigurationException ;
37
54
import org .bson .types .ObjectId ;
38
55
import org .jspecify .annotations .Nullable ;
39
56
import org .junit .jupiter .api .AfterEach ;
40
57
import org .junit .jupiter .api .Test ;
41
-
42
58
import org .springframework .context .ConfigurableApplicationContext ;
43
59
import org .springframework .context .support .GenericApplicationContext ;
44
60
import org .springframework .core .convert .ConversionFailedException ;
69
85
import org .springframework .data .mongodb .core .convert .LazyLoadingProxy ;
70
86
import org .springframework .data .mongodb .core .convert .MappingMongoConverter ;
71
87
import org .springframework .data .mongodb .core .convert .MongoCustomConversions ;
88
+ import org .springframework .data .mongodb .core .convert .MongoCustomConversions .BigDecimalRepresentation ;
72
89
import org .springframework .data .mongodb .core .convert .MongoCustomConversions .MongoConverterConfigurationAdapter ;
73
90
import org .springframework .data .mongodb .core .convert .NoOpDbRefResolver ;
74
91
import org .springframework .data .mongodb .core .geo .GeoJsonPoint ;
@@ -144,6 +161,12 @@ public class MongoTemplateTests {
144
161
it .defaultDb (DB_NAME );
145
162
});
146
163
164
+ cfg .configureConversion (it -> {
165
+ it .customConverters (adapter -> {
166
+ adapter .bigDecimal (BigDecimalRepresentation .DECIMAL128 );
167
+ });
168
+ });
169
+
147
170
cfg .configureMappingContext (it -> {
148
171
it .autocreateIndex (false );
149
172
it .initialEntitySet (AuditablePerson .class );
@@ -170,7 +193,10 @@ public class MongoTemplateTests {
170
193
});
171
194
172
195
cfg .configureConversion (it -> {
173
- it .customConverters (DateToDateTimeConverter .INSTANCE , DateTimeToDateConverter .INSTANCE );
196
+ it .customConverters (adapter -> {
197
+ adapter .registerConverters (List .of (DateToDateTimeConverter .INSTANCE , DateTimeToDateConverter .INSTANCE ))
198
+ .bigDecimal (BigDecimalRepresentation .DECIMAL128 );
199
+ });
174
200
});
175
201
176
202
cfg .configureMappingContext (it -> {
@@ -732,7 +758,7 @@ public void testDistinct() {
732
758
.containsExactlyInAnyOrder (person1 .getName (), person2 .getName ());
733
759
assertThat (template .findDistinct (new BasicQuery ("{'address.state' : 'PA'}" ), "name" ,
734
760
template .getCollectionName (MyPerson .class ), MyPerson .class , String .class ))
735
- .containsExactlyInAnyOrder (person1 .getName (), person2 .getName ());
761
+ .containsExactlyInAnyOrder (person1 .getName (), person2 .getName ());
736
762
}
737
763
738
764
@ Test // DATAMONGO-1761
@@ -876,7 +902,7 @@ public void testUsingAnInQueryWithLongId() throws Exception {
876
902
}
877
903
878
904
@ Test // DATAMONGO-602, GH-4920
879
- public void testUsingAnInQueryWithBigIntegerId () throws Exception {
905
+ public void testUsingAnInQueryWithBigIntegerId () {
880
906
881
907
template .remove (new Query (), PersonWithIdPropertyOfTypeBigInteger .class );
882
908
@@ -887,6 +913,34 @@ public void testUsingAnInQueryWithBigIntegerId() throws Exception {
887
913
assertThatExceptionOfType (ConversionFailedException .class ).isThrownBy (() -> template .insert (p1 ));
888
914
}
889
915
916
+ @ Test // GH-5037
917
+ public void errorsIfNoBigNumberFormatDefined () {
918
+
919
+ template = new MongoTestTemplate (cfg -> {
920
+
921
+ cfg .configureDatabaseFactory (it -> {
922
+
923
+ it .client (client );
924
+ it .defaultDb (DB_NAME );
925
+ });
926
+
927
+ cfg .configureConversion (it -> {
928
+ it .customConverters (adapter -> {
929
+ // no numeric conversion
930
+ });
931
+ });
932
+
933
+ });
934
+
935
+ template .remove (new Query (), PersonWithIdPropertyOfTypeBigInteger .class );
936
+
937
+ PersonWithIdPropertyOfTypeBigInteger p1 = new PersonWithIdPropertyOfTypeBigInteger ();
938
+ p1 .setFirstName ("Sven" );
939
+ p1 .setAge (11 );
940
+ p1 .setId (new BigInteger ("2666666666666666665" ));
941
+ assertThatExceptionOfType (CodecConfigurationException .class ).isThrownBy (() -> template .insert (p1 ));
942
+ }
943
+
890
944
@ Test
891
945
public void testUsingAnInQueryWithPrimitiveIntId () throws Exception {
892
946
@@ -2561,16 +2615,15 @@ public void shouldReadNestedProjection() {
2561
2615
walter .address = new Address ("spring" , "data" );
2562
2616
template .save (walter );
2563
2617
2564
- PersonPWA result = template .query (MyPerson .class )
2565
- .as (PersonPWA .class )
2566
- .matching (where ("id" ).is (walter .id ))
2618
+ PersonPWA result = template .query (MyPerson .class ).as (PersonPWA .class ).matching (where ("id" ).is (walter .id ))
2567
2619
.firstValue ();
2568
2620
2569
2621
assertThat (result .getAddress ().getCity ()).isEqualTo ("data" );
2570
2622
}
2571
2623
2572
2624
interface PersonPWA {
2573
2625
String getName ();
2626
+
2574
2627
AdressProjection getAddress ();
2575
2628
}
2576
2629
@@ -2823,7 +2876,7 @@ public void testFindAllAndRemoveFullyReturnsAndRemovesDocuments() {
2823
2876
2824
2877
assertThat (template .getDb ().getCollection ("sample" ).countDocuments (
2825
2878
new org .bson .Document ("field" , new org .bson .Document ("$in" , Arrays .asList ("spring" , "mongodb" )))))
2826
- .isEqualTo (0L );
2879
+ .isEqualTo (0L );
2827
2880
assertThat (template .getDb ().getCollection ("sample" ).countDocuments (new org .bson .Document ("field" , "data" )))
2828
2881
.isEqualTo (1L );
2829
2882
}
@@ -3935,7 +3988,8 @@ void saveEntityWithDotInFieldName() {
3935
3988
3936
3989
template .save (source );
3937
3990
3938
- org .bson .Document raw = template .execute (WithFieldNameContainingDots .class , collection -> collection .find (new org .bson .Document ("_id" , source .id )).first ());
3991
+ org .bson .Document raw = template .execute (WithFieldNameContainingDots .class ,
3992
+ collection -> collection .find (new org .bson .Document ("_id" , source .id )).first ());
3939
3993
assertThat (raw ).containsEntry ("field.name.with.dots" , "v1" );
3940
3994
}
3941
3995
@@ -3954,13 +4008,17 @@ void queryEntityWithDotInFieldNameUsingExpr() {
3954
4008
template .save (source );
3955
4009
template .save (source2 );
3956
4010
3957
- WithFieldNameContainingDots loaded = template .query (WithFieldNameContainingDots .class ) // with property -> fieldname mapping
3958
- .matching (expr (ComparisonOperators .valueOf (ObjectOperators .getValueOf ("value" )).equalToValue ("v1" ))).firstValue ();
4011
+ WithFieldNameContainingDots loaded = template .query (WithFieldNameContainingDots .class ) // with property -> fieldname
4012
+ // mapping
4013
+ .matching (expr (ComparisonOperators .valueOf (ObjectOperators .getValueOf ("value" )).equalToValue ("v1" )))
4014
+ .firstValue ();
3959
4015
3960
4016
assertThat (loaded ).isEqualTo (source );
3961
4017
3962
4018
loaded = template .query (WithFieldNameContainingDots .class ) // using raw fieldname
3963
- .matching (expr (ComparisonOperators .valueOf (ObjectOperators .getValueOf ("field.name.with.dots" )).equalToValue ("v1" ))).firstValue ();
4019
+ .matching (
4020
+ expr (ComparisonOperators .valueOf (ObjectOperators .getValueOf ("field.name.with.dots" )).equalToValue ("v1" )))
4021
+ .firstValue ();
3964
4022
3965
4023
assertThat (loaded ).isEqualTo (source );
3966
4024
}
@@ -3975,20 +4033,20 @@ void updateEntityWithDotInFieldNameUsingAggregations() {
3975
4033
3976
4034
template .save (source );
3977
4035
3978
- template .update (WithFieldNameContainingDots .class )
3979
- .matching (where ("id" ).is (source .id ))
3980
- .apply (AggregationUpdate .newUpdate (ReplaceWithOperation .replaceWithValue (ObjectOperators .setValueTo ("value" , "changed" ))))
3981
- .first ();
4036
+ template .update (WithFieldNameContainingDots .class ).matching (where ("id" ).is (source .id )).apply (AggregationUpdate
4037
+ .newUpdate (ReplaceWithOperation .replaceWithValue (ObjectOperators .setValueTo ("value" , "changed" )))).first ();
3982
4038
3983
- org .bson .Document raw = template .execute (WithFieldNameContainingDots .class , collection -> collection .find (new org .bson .Document ("_id" , source .id )).first ());
4039
+ org .bson .Document raw = template .execute (WithFieldNameContainingDots .class ,
4040
+ collection -> collection .find (new org .bson .Document ("_id" , source .id )).first ());
3984
4041
assertThat (raw ).containsEntry ("field.name.with.dots" , "changed" );
3985
4042
3986
- template .update (WithFieldNameContainingDots .class )
3987
- .matching ( where ( "id" ). is ( source . id ))
3988
- . apply ( AggregationUpdate . newUpdate ( ReplaceWithOperation .replaceWithValue (ObjectOperators .setValueTo ("field.name.with.dots" , "changed-again" ))))
4043
+ template .update (WithFieldNameContainingDots .class ). matching ( where ( "id" ). is ( source . id ))
4044
+ .apply ( AggregationUpdate . newUpdate (
4045
+ ReplaceWithOperation .replaceWithValue (ObjectOperators .setValueTo ("field.name.with.dots" , "changed-again" ))))
3989
4046
.first ();
3990
4047
3991
- raw = template .execute (WithFieldNameContainingDots .class , collection -> collection .find (new org .bson .Document ("_id" , source .id )).first ());
4048
+ raw = template .execute (WithFieldNameContainingDots .class ,
4049
+ collection -> collection .find (new org .bson .Document ("_id" , source .id )).first ());
3992
4050
assertThat (raw ).containsEntry ("field.name.with.dots" , "changed-again" );
3993
4051
}
3994
4052
@@ -4013,9 +4071,8 @@ void savesMapWithDotInKey() {
4013
4071
org .bson .Document raw = template .execute (WithFieldNameContainingDots .class ,
4014
4072
collection -> collection .find (new org .bson .Document ("_id" , source .id )).first ());
4015
4073
4016
- assertThat (raw .get ("mapValue" , org .bson .Document .class ))
4017
- .containsEntry ("k1" , "v1" )
4018
- .containsEntry ("map.key.with.dot" , "v2" );
4074
+ assertThat (raw .get ("mapValue" , org .bson .Document .class )).containsEntry ("k1" , "v1" ).containsEntry ("map.key.with.dot" ,
4075
+ "v2" );
4019
4076
}
4020
4077
4021
4078
@ Test // GH-4464
@@ -4031,16 +4088,13 @@ void readsMapWithDotInKey() {
4031
4088
MongoTemplate template = new MongoTemplate (new SimpleMongoClientDatabaseFactory (client , DB_NAME ), converter );
4032
4089
4033
4090
Map <String , String > sourceMap = Map .of ("k1" , "v1" , "sourceMap.key.with.dot" , "v2" );
4034
- template .execute (WithFieldNameContainingDots .class ,
4035
- collection -> {
4036
- collection .insertOne (new org .bson .Document ("_id" , "id-1" ).append ("mapValue" , sourceMap ));
4037
- return null ;
4038
- }
4039
- );
4091
+ template .execute (WithFieldNameContainingDots .class , collection -> {
4092
+ collection .insertOne (new org .bson .Document ("_id" , "id-1" ).append ("mapValue" , sourceMap ));
4093
+ return null ;
4094
+ });
4040
4095
4041
4096
WithFieldNameContainingDots loaded = template .query (WithFieldNameContainingDots .class )
4042
- .matching (where ("id" ).is ("id-1" ))
4043
- .firstValue ();
4097
+ .matching (where ("id" ).is ("id-1" )).firstValue ();
4044
4098
4045
4099
assertThat (loaded .mapValue ).isEqualTo (sourceMap );
4046
4100
}
@@ -5015,8 +5069,7 @@ static class WithFieldNameContainingDots {
5015
5069
5016
5070
String id ;
5017
5071
5018
- @ Field (value = "field.name.with.dots" , nameType = Type .KEY )
5019
- String value ;
5072
+ @ Field (value = "field.name.with.dots" , nameType = Type .KEY ) String value ;
5020
5073
5021
5074
Map <String , String > mapValue ;
5022
5075
@@ -5034,7 +5087,8 @@ public boolean equals(Object o) {
5034
5087
return false ;
5035
5088
}
5036
5089
WithFieldNameContainingDots withFieldNameContainingDots = (WithFieldNameContainingDots ) o ;
5037
- return Objects .equals (id , withFieldNameContainingDots .id ) && Objects .equals (value , withFieldNameContainingDots .value )
5090
+ return Objects .equals (id , withFieldNameContainingDots .id )
5091
+ && Objects .equals (value , withFieldNameContainingDots .value )
5038
5092
&& Objects .equals (mapValue , withFieldNameContainingDots .mapValue );
5039
5093
}
5040
5094
0 commit comments