1818import java .lang .reflect .Field ;
1919import java .lang .reflect .Method ;
2020import java .lang .reflect .Modifier ;
21- import java .util .Collection ;
2221import java .util .Collections ;
23- import java .util .LinkedHashSet ;
22+ import java .util .HashSet ;
2423import java .util .Map ;
2524import java .util .Optional ;
2625import java .util .Set ;
27- import java .util .function . Supplier ;
26+ import java .util .stream . Collectors ;
2827
2928import org .springframework .data .mapping .Association ;
3029import org .springframework .data .mapping .PersistentEntity ;
3130import org .springframework .data .mapping .PersistentProperty ;
3231import org .springframework .data .util .Lazy ;
33- import org .springframework .data .util .NullableWrapperConverters ;
3432import org .springframework .data .util .ReflectionUtils ;
3533import org .springframework .data .util .TypeInformation ;
3634import org .springframework .lang .Nullable ;
@@ -64,11 +62,10 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
6462 private final Property property ;
6563 private final Lazy <Integer > hashCode ;
6664 private final Lazy <Boolean > usePropertyAccess ;
67- private final Lazy <TypeInformation <?>> entityTypeInformation ;
65+ private final Lazy <Set < TypeInformation <?> >> entityTypeInformation ;
6866
6967 private final Lazy <Boolean > isAssociation ;
7068 private final Lazy <TypeInformation <?>> associationTargetType ;
71- private final Lazy <Collection <TypeInformation <?>>> entityTypes ;
7269
7370 private final Method getter ;
7471 private final Method setter ;
@@ -100,10 +97,7 @@ public AbstractPersistentProperty(Property property, PersistentEntity<?, P> owne
10097 .map (TypeInformation ::getComponentType ) //
10198 .orElse (null ));
10299
103- this .entityTypeInformation = Lazy .of (() -> Optional .ofNullable (getAssociationOrActualType ())
104- .filter (it -> !simpleTypeHolder .isSimpleType (it .getType ())) //
105- .filter (it -> !it .isCollectionLike ()) //
106- .filter (it -> !it .isMap ()).orElse (null ));
100+ this .entityTypeInformation = Lazy .of (() -> detectEntityTypes (simpleTypeHolder ));
107101
108102 this .getter = property .getGetter ().orElse (null );
109103 this .setter = property .getSetter ().orElse (null );
@@ -115,45 +109,6 @@ public AbstractPersistentProperty(Property property, PersistentEntity<?, P> owne
115109 } else {
116110 this .immutable = false ;
117111 }
118-
119- this .entityTypes = Lazy .of (() -> collectEntityTypes (simpleTypeHolder , information , new LinkedHashSet <>()));
120- }
121-
122- protected Set <TypeInformation <?>> collectEntityTypes (SimpleTypeHolder simpleTypeHolder ,
123- @ Nullable TypeInformation <?> typeInformation , Set <TypeInformation <?>> entityTypes ) {
124-
125- if (typeInformation == null || entityTypes .contains (typeInformation )
126- || simpleTypeHolder .isSimpleType (typeInformation .getType ())) {
127- return entityTypes ;
128- }
129-
130- if (typeInformation .isMap ()) {
131-
132- collectEntityTypes (simpleTypeHolder , typeInformation .getComponentType (), entityTypes );
133- collectEntityTypes (simpleTypeHolder , typeInformation .getMapValueType (), entityTypes );
134- return entityTypes ;
135- }
136-
137- if (typeInformation .isCollectionLike ()) {
138-
139- collectEntityTypes (simpleTypeHolder , typeInformation .getComponentType (), entityTypes );
140- return entityTypes ;
141- }
142-
143- if (NullableWrapperConverters .supports (typeInformation .getType ())) {
144-
145- collectEntityTypes (simpleTypeHolder , typeInformation .getActualType (), entityTypes );
146- return entityTypes ;
147- }
148-
149- if (ASSOCIATION_TYPE != null && ASSOCIATION_TYPE .isAssignableFrom (typeInformation .getType ())) {
150-
151- entityTypes .add (getAssociationOrActualType ());
152- return entityTypes ;
153- }
154-
155- entityTypes .add (typeInformation );
156- return entityTypes ;
157112 }
158113
159114 protected abstract Association <P > createAssociation ();
@@ -211,14 +166,14 @@ public TypeInformation<?> getTypeInformation() {
211166 public Iterable <? extends TypeInformation <?>> getPersistentEntityTypes () {
212167
213168 if (isMap () || isCollectionLike ()) {
214- return entityTypes .get ();
169+ return entityTypeInformation .get ();
215170 }
216171
217172 if (!isEntity ()) {
218173 return Collections .emptySet ();
219174 }
220175
221- return entityTypes .get ();
176+ return entityTypeInformation .get ();
222177 }
223178
224179 /*
@@ -362,7 +317,7 @@ public boolean isArray() {
362317 */
363318 @ Override
364319 public boolean isEntity () {
365- return !isTransient () && entityTypeInformation .getNullable () != null ;
320+ return !isTransient () && ! entityTypeInformation .get (). isEmpty () ;
366321 }
367322
368323 /*
@@ -401,7 +356,11 @@ public Class<?> getMapValueType() {
401356 */
402357 @ Override
403358 public Class <?> getActualType () {
404- return getRequiredAssociationOrActualType ().getType ();
359+
360+ TypeInformation <?> targetType = associationTargetType .getNullable ();
361+ TypeInformation <?> result = targetType == null ? information .getRequiredActualType () : targetType ;
362+
363+ return result .getType ();
405364 }
406365
407366 /*
@@ -454,23 +413,40 @@ public String toString() {
454413 return property .toString ();
455414 }
456415
457- @ Nullable
458- private TypeInformation <?> getAssociationOrActualType () {
459- return getAssociationTypeOr (() -> information .getActualType ());
460- }
416+ private Set <TypeInformation <?>> detectEntityTypes (SimpleTypeHolder simpleTypes ) {
417+
418+ TypeInformation <?> typeToStartWith = ASSOCIATION_TYPE != null && ASSOCIATION_TYPE .isAssignableFrom (rawType )
419+ ? information .getComponentType ()
420+ : information ;
421+
422+ Set <TypeInformation <?>> result = detectEntityTypes (typeToStartWith );
461423
462- private TypeInformation <?> getRequiredAssociationOrActualType () {
463- return getAssociationTypeOr (() -> information .getRequiredActualType ());
424+ return result .stream ()
425+ .filter (it -> !simpleTypes .isSimpleType (it .getType ()))
426+ .filter (it -> !it .getType ().equals (ASSOCIATION_TYPE ))
427+ .collect (Collectors .toSet ());
464428 }
465429
466- private TypeInformation <?> getAssociationTypeOr ( Supplier < TypeInformation <?>> fallback ) {
430+ private Set < TypeInformation <?>> detectEntityTypes ( @ Nullable TypeInformation <?> source ) {
467431
468- TypeInformation <?> result = associationTargetType .getNullable ();
432+ if (source == null ) {
433+ return Collections .emptySet ();
434+ }
435+
436+ Set <TypeInformation <?>> result = new HashSet <>();
469437
470- if (result != null ) {
471- return result ;
438+ if (source .isMap ()) {
439+ result .addAll (detectEntityTypes (source .getComponentType ()));
440+ }
441+
442+ TypeInformation <?> actualType = source .getActualType ();
443+
444+ if (source .equals (actualType )) {
445+ result .add (source );
446+ } else {
447+ result .addAll (detectEntityTypes (actualType ));
472448 }
473449
474- return fallback . get () ;
450+ return result ;
475451 }
476452}
0 commit comments