24
24
import java .util .concurrent .TimeUnit ;
25
25
26
26
import org .bson .BsonNull ;
27
+ import org .bson .BsonValue ;
27
28
import org .bson .Document ;
28
29
import org .jspecify .annotations .Nullable ;
29
30
import org .springframework .core .convert .ConversionService ;
30
31
import org .springframework .core .env .Environment ;
31
32
import org .springframework .core .env .EnvironmentCapable ;
33
+ import org .springframework .core .env .StandardEnvironment ;
32
34
import org .springframework .dao .InvalidDataAccessApiUsageException ;
33
35
import org .springframework .data .convert .CustomConversions ;
34
36
import org .springframework .data .expression .ValueEvaluationContext ;
64
66
import org .springframework .data .projection .TargetAware ;
65
67
import org .springframework .data .util .Optionals ;
66
68
import org .springframework .expression .spel .support .SimpleEvaluationContext ;
69
+ import org .springframework .lang .Contract ;
67
70
import org .springframework .util .Assert ;
68
71
import org .springframework .util .ClassUtils ;
69
72
import org .springframework .util .LinkedMultiValueMap ;
@@ -413,7 +416,7 @@ interface Entity<T> {
413
416
*
414
417
* @return
415
418
*/
416
- Object getId ();
419
+ @ Nullable Object getId ();
417
420
418
421
/**
419
422
* Returns the property value for {@code key}.
@@ -521,7 +524,7 @@ interface AdaptibleEntity<T> extends Entity<T> {
521
524
* @param id must not be {@literal null}.
522
525
* @return
523
526
*/
524
- @ Nullable
527
+ @ Contract ( "null -> fail" )
525
528
T populateIdIfNecessary (@ Nullable Object id );
526
529
527
530
/**
@@ -564,12 +567,12 @@ public String getIdFieldName() {
564
567
}
565
568
566
569
@ Override
567
- public Object getId () {
570
+ public @ Nullable Object getId () {
568
571
return getPropertyValue (ID_FIELD );
569
572
}
570
573
571
574
@ Override
572
- public Object getPropertyValue (String key ) {
575
+ public @ Nullable Object getPropertyValue (String key ) {
573
576
return map .get (key );
574
577
}
575
578
@@ -579,7 +582,7 @@ public Query getByIdQuery() {
579
582
}
580
583
581
584
@ Override
582
- public @ Nullable T populateIdIfNecessary (@ Nullable Object id ) {
585
+ public T populateIdIfNecessary (@ Nullable Object id ) {
583
586
584
587
map .put (ID_FIELD , id );
585
588
@@ -721,7 +724,7 @@ public Object getId() {
721
724
}
722
725
723
726
@ Override
724
- public Object getPropertyValue (String key ) {
727
+ public @ Nullable Object getPropertyValue (String key ) {
725
728
return propertyAccessor .getProperty (entity .getRequiredPersistentProperty (key ));
726
729
}
727
730
@@ -836,7 +839,6 @@ public Map<String, Object> extractKeys(Document sortObject, Class<?> sourceType)
836
839
return keyset ;
837
840
}
838
841
839
- @ Nullable
840
842
private Object getNestedPropertyValue (String key ) {
841
843
842
844
String [] segments = key .split ("\\ ." );
@@ -849,6 +851,10 @@ private Object getNestedPropertyValue(String key) {
849
851
currentValue = currentEntity .getPropertyValue (segment );
850
852
851
853
if (i < segments .length - 1 ) {
854
+ if (currentValue == null ) {
855
+ return BsonNull .VALUE ;
856
+ }
857
+
852
858
currentEntity = entityOperations .forEntity (currentValue );
853
859
}
854
860
}
@@ -886,7 +892,7 @@ private static <T> AdaptibleEntity<T> of(T bean,
886
892
}
887
893
888
894
@ Override
889
- public @ Nullable T populateIdIfNecessary (@ Nullable Object id ) {
895
+ public T populateIdIfNecessary (@ Nullable Object id ) {
890
896
891
897
if (id == null ) {
892
898
return propertyAccessor .getBean ();
@@ -1122,7 +1128,7 @@ public TimeSeriesOptions mapTimeSeriesOptions(TimeSeriesOptions source) {
1122
1128
1123
1129
@ Override
1124
1130
public String getIdKeyName () {
1125
- return entity .getIdProperty (). getName ();
1131
+ return entity .getIdProperty () != null ? entity . getIdProperty (). getName () : ID_FIELD ;
1126
1132
}
1127
1133
1128
1134
private String mappedNameOrDefault (String name ) {
@@ -1142,7 +1148,7 @@ private ValueEvaluationContext getEvaluationContextForEntity(@Nullable Persisten
1142
1148
return mongoEntity .getValueEvaluationContext (null );
1143
1149
}
1144
1150
1145
- return ValueEvaluationContext .of (this .environment , SimpleEvaluationContext .forReadOnlyDataBinding ().build ());
1151
+ return ValueEvaluationContext .of (this .environment != null ? this . environment : new StandardEnvironment () , SimpleEvaluationContext .forReadOnlyDataBinding ().build ());
1146
1152
}
1147
1153
1148
1154
/**
0 commit comments