|
22 | 22 |
|
23 | 23 | import java.lang.annotation.Annotation;
|
24 | 24 | import java.lang.reflect.Constructor;
|
| 25 | +import java.lang.reflect.RecordComponent; |
25 | 26 | import java.util.ArrayList;
|
26 | 27 | import java.util.Arrays;
|
27 | 28 | import java.util.List;
|
|
34 | 35 | import org.springframework.data.mapping.PersistentEntity;
|
35 | 36 | import org.springframework.data.mapping.PersistentProperty;
|
36 | 37 | import org.springframework.data.mapping.PreferredConstructor;
|
37 |
| -import org.springframework.data.util.ClassTypeInformation; |
38 | 38 | import org.springframework.data.util.KotlinReflectionUtils;
|
39 | 39 | import org.springframework.data.util.TypeInformation;
|
40 | 40 | import org.springframework.lang.Nullable;
|
41 | 41 | import org.springframework.util.Assert;
|
| 42 | +import org.springframework.util.ClassUtils; |
42 | 43 |
|
43 | 44 | /**
|
44 | 45 | * Helper class to find a {@link PreferredConstructor}.
|
|
49 | 50 | * @author Mark Paluch
|
50 | 51 | * @author Xeno Amess
|
51 | 52 | */
|
52 |
| -public interface PreferredConstructorDiscoverer<T, P extends PersistentProperty<P>> { |
| 53 | +public interface PreferredConstructorDiscoverer { |
53 | 54 |
|
54 | 55 | /**
|
55 | 56 | * Discovers the {@link PreferredConstructor} for the given type.
|
@@ -124,12 +125,45 @@ <T, P extends PersistentProperty<P>> PreferredConstructor<T, P> discover(TypeInf
|
124 | 125 | }
|
125 | 126 | }
|
126 | 127 |
|
| 128 | + if (rawOwningType.isRecord() && (candidates.size() > 1 || (noArg != null && !candidates.isEmpty()))) { |
| 129 | + return RECORD.discover(type, entity); |
| 130 | + } |
| 131 | + |
127 | 132 | if (noArg != null) {
|
128 | 133 | return buildPreferredConstructor(noArg, type, entity);
|
129 | 134 | }
|
130 | 135 |
|
131 |
| - return candidates.size() > 1 || candidates.isEmpty() ? null |
132 |
| - : buildPreferredConstructor(candidates.iterator().next(), type, entity); |
| 136 | + if (candidates.size() == 1) { |
| 137 | + return buildPreferredConstructor(candidates.iterator().next(), type, entity); |
| 138 | + } |
| 139 | + |
| 140 | + return null; |
| 141 | + } |
| 142 | + }, |
| 143 | + |
| 144 | + /** |
| 145 | + * Discovers the canonical constructor for Java Record types. |
| 146 | + * |
| 147 | + * @since 3.0 |
| 148 | + */ |
| 149 | + RECORD { |
| 150 | + |
| 151 | + @Nullable |
| 152 | + @Override |
| 153 | + <T, P extends PersistentProperty<P>> PreferredConstructor<T, P> discover(TypeInformation<T> type, |
| 154 | + @Nullable PersistentEntity<T, P> entity) { |
| 155 | + |
| 156 | + Class<?> rawOwningType = type.getType(); |
| 157 | + |
| 158 | + if (!rawOwningType.isRecord()) { |
| 159 | + return null; |
| 160 | + } |
| 161 | + |
| 162 | + Class<?>[] paramTypes = Arrays.stream(rawOwningType.getRecordComponents()).map(RecordComponent::getType) |
| 163 | + .toArray(Class<?>[]::new); |
| 164 | + Constructor<?> canonicalConstructor = ClassUtils.getConstructorIfAvailable(rawOwningType, paramTypes); |
| 165 | + |
| 166 | + return canonicalConstructor != null ? buildPreferredConstructor(canonicalConstructor, type, entity) : null; |
133 | 167 | }
|
134 | 168 | },
|
135 | 169 |
|
|
0 commit comments