30
30
import org .springframework .data .mapping .MappingException ;
31
31
import org .springframework .data .mapping .PersistentEntity ;
32
32
import org .springframework .data .mapping .PersistentPropertyAccessor ;
33
+ import org .springframework .data .mapping .PersistentPropertyPath ;
34
+ import org .springframework .data .mapping .PropertyPath ;
33
35
import org .springframework .data .mapping .context .MappingContext ;
34
36
import org .springframework .data .mapping .model .ConvertingPropertyAccessor ;
35
37
import org .springframework .data .mongodb .core .CollectionOptions .TimeSeriesOptions ;
50
52
import org .springframework .data .projection .EntityProjection ;
51
53
import org .springframework .data .projection .EntityProjectionIntrospector ;
52
54
import org .springframework .data .projection .ProjectionFactory ;
55
+ import org .springframework .data .projection .TargetAware ;
53
56
import org .springframework .data .util .Optionals ;
54
57
import org .springframework .lang .Nullable ;
55
58
import org .springframework .util .Assert ;
@@ -117,12 +120,16 @@ <T> Entity<T> forEntity(T entity) {
117
120
118
121
Assert .notNull (entity , "Bean must not be null" );
119
122
123
+ if (entity instanceof TargetAware targetAware ) {
124
+ return new SimpleMappedEntity ((Map <String , Object >) targetAware .getTarget (), this );
125
+ }
126
+
120
127
if (entity instanceof String ) {
121
- return new UnmappedEntity (parse (entity .toString ()));
128
+ return new UnmappedEntity (parse (entity .toString ()), this );
122
129
}
123
130
124
131
if (entity instanceof Map ) {
125
- return new SimpleMappedEntity ((Map <String , Object >) entity );
132
+ return new SimpleMappedEntity ((Map <String , Object >) entity , this );
126
133
}
127
134
128
135
return MappedEntity .of (entity , context , this );
@@ -142,11 +149,11 @@ <T> AdaptibleEntity<T> forEntity(T entity, ConversionService conversionService)
142
149
Assert .notNull (conversionService , "ConversionService must not be null" );
143
150
144
151
if (entity instanceof String ) {
145
- return new UnmappedEntity (parse (entity .toString ()));
152
+ return new UnmappedEntity (parse (entity .toString ()), this );
146
153
}
147
154
148
155
if (entity instanceof Map ) {
149
- return new SimpleMappedEntity ((Map <String , Object >) entity );
156
+ return new SimpleMappedEntity ((Map <String , Object >) entity , this );
150
157
}
151
158
152
159
return AdaptibleMappedEntity .of (entity , context , conversionService , this );
@@ -287,7 +294,8 @@ public <T> TypedOperations<T> forType(@Nullable Class<T> entityClass) {
287
294
*/
288
295
public <M , D > EntityProjection <M , D > introspectProjection (Class <M > resultType , Class <D > entityType ) {
289
296
290
- if (!queryMapper .getMappingContext ().hasPersistentEntityFor (entityType )) {
297
+ MongoPersistentEntity <?> persistentEntity = queryMapper .getMappingContext ().getPersistentEntity (entityType );
298
+ if (persistentEntity == null && !resultType .isInterface () || ClassUtils .isAssignable (Document .class , resultType )) {
291
299
return (EntityProjection ) EntityProjection .nonProjecting (resultType );
292
300
}
293
301
return introspector .introspect (resultType , entityType );
@@ -369,6 +377,7 @@ private Document getMappedValidator(Validator validator, Class<?> domainType) {
369
377
* A representation of information about an entity.
370
378
*
371
379
* @author Oliver Gierke
380
+ * @author Christoph Strobl
372
381
* @since 2.1
373
382
*/
374
383
interface Entity <T > {
@@ -471,10 +480,10 @@ default boolean isVersionedEntity() {
471
480
/**
472
481
* @param sortObject
473
482
* @return
474
- * @since 3 .1
483
+ * @since 4 .1
475
484
* @throws IllegalStateException if a sort key yields {@literal null}.
476
485
*/
477
- Map <String , Object > extractKeys (Document sortObject );
486
+ Map <String , Object > extractKeys (Document sortObject , Class <?> sourceType );
478
487
479
488
}
480
489
@@ -523,9 +532,11 @@ interface AdaptibleEntity<T> extends Entity<T> {
523
532
private static class UnmappedEntity <T extends Map <String , Object >> implements AdaptibleEntity <T > {
524
533
525
534
private final T map ;
535
+ private final EntityOperations entityOperations ;
526
536
527
- protected UnmappedEntity (T map ) {
537
+ protected UnmappedEntity (T map , EntityOperations entityOperations ) {
528
538
this .map = map ;
539
+ this .entityOperations = entityOperations ;
529
540
}
530
541
531
542
@ Override
@@ -596,13 +607,19 @@ public boolean isNew() {
596
607
}
597
608
598
609
@ Override
599
- public Map <String , Object > extractKeys (Document sortObject ) {
610
+ public Map <String , Object > extractKeys (Document sortObject , Class <?> sourceType ) {
600
611
601
612
Map <String , Object > keyset = new LinkedHashMap <>();
602
- keyset .put (ID_FIELD , getId ());
613
+ MongoPersistentEntity <?> sourceEntity = entityOperations .context .getPersistentEntity (sourceType );
614
+ if (sourceEntity != null && sourceEntity .hasIdProperty ()) {
615
+ keyset .put (sourceEntity .getRequiredIdProperty ().getName (), getId ());
616
+ } else {
617
+ keyset .put (ID_FIELD , getId ());
618
+ }
603
619
604
620
for (String key : sortObject .keySet ()) {
605
- Object value = BsonUtils .resolveValue (map , key );
621
+
622
+ Object value = resolveValue (key , sourceEntity );
606
623
607
624
if (value == null ) {
608
625
throw new IllegalStateException (
@@ -614,12 +631,24 @@ public Map<String, Object> extractKeys(Document sortObject) {
614
631
615
632
return keyset ;
616
633
}
634
+
635
+ @ Nullable
636
+ private Object resolveValue (String key , @ Nullable MongoPersistentEntity <?> sourceEntity ) {
637
+
638
+ if (sourceEntity == null ) {
639
+ return BsonUtils .resolveValue (map , key );
640
+ }
641
+ PropertyPath from = PropertyPath .from (key , sourceEntity .getTypeInformation ());
642
+ PersistentPropertyPath <MongoPersistentProperty > persistentPropertyPath = entityOperations .context
643
+ .getPersistentPropertyPath (from );
644
+ return BsonUtils .resolveValue (map , persistentPropertyPath .toDotPath (p -> p .getFieldName ()));
645
+ }
617
646
}
618
647
619
648
private static class SimpleMappedEntity <T extends Map <String , Object >> extends UnmappedEntity <T > {
620
649
621
- protected SimpleMappedEntity (T map ) {
622
- super (map );
650
+ protected SimpleMappedEntity (T map , EntityOperations entityOperations ) {
651
+ super (map , entityOperations );
623
652
}
624
653
625
654
@ Override
@@ -758,10 +787,15 @@ public boolean isNew() {
758
787
}
759
788
760
789
@ Override
761
- public Map <String , Object > extractKeys (Document sortObject ) {
790
+ public Map <String , Object > extractKeys (Document sortObject , Class <?> sourceType ) {
762
791
763
792
Map <String , Object > keyset = new LinkedHashMap <>();
764
- keyset .put (entity .getRequiredIdProperty ().getName (), getId ());
793
+ MongoPersistentEntity <?> sourceEntity = entityOperations .context .getPersistentEntity (sourceType );
794
+ if (sourceEntity != null && sourceEntity .hasIdProperty ()) {
795
+ keyset .put (sourceEntity .getRequiredIdProperty ().getName (), getId ());
796
+ } else {
797
+ keyset .put (entity .getRequiredIdProperty ().getName (), getId ());
798
+ }
765
799
766
800
for (String key : sortObject .keySet ()) {
767
801
@@ -933,6 +967,14 @@ interface TypedOperations<T> {
933
967
* @since 3.3
934
968
*/
935
969
TimeSeriesOptions mapTimeSeriesOptions (TimeSeriesOptions options );
970
+
971
+ /**
972
+ * @return the name of the id field.
973
+ * @since 4.1
974
+ */
975
+ default String getIdKeyName () {
976
+ return ID_FIELD ;
977
+ }
936
978
}
937
979
938
980
/**
@@ -1055,6 +1097,11 @@ private String mappedNameOrDefault(String name) {
1055
1097
MongoPersistentProperty persistentProperty = entity .getPersistentProperty (name );
1056
1098
return persistentProperty != null ? persistentProperty .getFieldName () : name ;
1057
1099
}
1100
+
1101
+ @ Override
1102
+ public String getIdKeyName () {
1103
+ return entity .getIdProperty ().getName ();
1104
+ }
1058
1105
}
1059
1106
1060
1107
}
0 commit comments