diff --git a/src/main/java/org/springframework/data/mapping/model/PreferredConstructorDiscoverer.java b/src/main/java/org/springframework/data/mapping/model/PreferredConstructorDiscoverer.java index a70effd80..57169dc2d 100644 --- a/src/main/java/org/springframework/data/mapping/model/PreferredConstructorDiscoverer.java +++ b/src/main/java/org/springframework/data/mapping/model/PreferredConstructorDiscoverer.java @@ -22,11 +22,13 @@ import kotlin.reflect.jvm.ReflectJvmMapping; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.ParameterNameDiscoverer; +import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.PreferredConstructor; @@ -102,42 +104,33 @@ public interface PreferredConstructorDiscoverer> PreferredConstructor discover(TypeInformation type, @Nullable PersistentEntity entity) { - boolean noArgConstructorFound = false; - int numberOfArgConstructors = 0; Class rawOwningType = type.getType(); - PreferredConstructor constructor = null; + List> candidates = new ArrayList<>(); + Constructor noArg = null; for (Constructor candidate : rawOwningType.getDeclaredConstructors()) { - PreferredConstructor preferredConstructor = buildPreferredConstructor(candidate, type, entity); - // Synthetic constructors should not be considered - if (preferredConstructor.getConstructor().isSynthetic()) { + if (candidate.isSynthetic()) { continue; } - // Explicitly defined constructor trumps all - if (preferredConstructor.isExplicitlyAnnotated()) { - return preferredConstructor; + if(candidate.isAnnotationPresent(PersistenceConstructor.class)) { + return buildPreferredConstructor(candidate, type, entity); } - // No-arg constructor trumps custom ones - if (constructor == null || preferredConstructor.isNoArgConstructor()) { - constructor = preferredConstructor; - } - - if (preferredConstructor.isNoArgConstructor()) { - noArgConstructorFound = true; + if(candidate.getParameterCount() == 0) { + noArg = candidate; } else { - numberOfArgConstructors++; + candidates.add(candidate); } } - if (!noArgConstructorFound && numberOfArgConstructors > 1) { - constructor = null; + if(noArg != null) { + return buildPreferredConstructor(noArg, type, entity); } - return constructor; + return candidates.size() > 1 || candidates.isEmpty() ? null : buildPreferredConstructor(candidates.iterator().next(), type, entity); } }, @@ -158,9 +151,9 @@ public interface PreferredConstructorDiscoverer rawOwningType = type.getType(); return Arrays.stream(rawOwningType.getDeclaredConstructors()) // + .filter(it -> !it.isSynthetic()) // Synthetic constructors should not be considered + .filter(it -> it.isAnnotationPresent(PersistenceConstructor.class)) // Explicitly defined constructor trumps all .map(it -> buildPreferredConstructor(it, type, entity)) // - .filter(it -> !it.getConstructor().isSynthetic()) // Synthetic constructors should not be considered - .filter(PreferredConstructor::isExplicitlyAnnotated) // Explicitly defined constructor trumps all .findFirst() // .orElseGet(() -> {