15
15
*/
16
16
package org .springframework .data .jpa .repository .support ;
17
17
18
+ import jakarta .persistence .Column ;
18
19
import jakarta .persistence .IdClass ;
19
20
import jakarta .persistence .PersistenceUnitUtil ;
20
21
import jakarta .persistence .Tuple ;
44
45
import org .springframework .data .util .DirectFieldAccessFallbackBeanWrapper ;
45
46
import org .springframework .lang .Nullable ;
46
47
import org .springframework .util .Assert ;
48
+ import org .springframework .util .StringUtils ;
47
49
48
50
/**
49
51
* Implementation of {@link org.springframework.data.repository.core.EntityInformation} that uses JPA {@link Metamodel}
55
57
* @author Mark Paluch
56
58
* @author Jens Schauder
57
59
* @author Greg Turnquist
60
+ * @author Yanming Zhou
58
61
*/
59
62
public class JpaMetamodelEntityInformation <T , ID > extends JpaEntityInformationSupport <T , ID > {
60
63
@@ -236,12 +239,14 @@ public Map<String, Object> getKeyset(Iterable<String> propertyPaths, T entity) {
236
239
237
240
Map <String , Object > keyset = new LinkedHashMap <>();
238
241
239
- if (hasCompositeId ()) {
240
- for (String idAttributeName : getIdAttributeNames ()) {
241
- keyset .put (idAttributeName , getter .apply (idAttributeName ));
242
+ if (!isKeysetQualified (propertyPaths )) {
243
+ if (hasCompositeId ()) {
244
+ for (String idAttributeName : getIdAttributeNames ()) {
245
+ keyset .put (idAttributeName , getter .apply (idAttributeName ));
246
+ }
247
+ } else {
248
+ keyset .put (getIdAttribute ().getName (), getId (entity ));
242
249
}
243
- } else {
244
- keyset .put (getIdAttribute ().getName (), getId (entity ));
245
250
}
246
251
247
252
for (String propertyPath : propertyPaths ) {
@@ -251,6 +256,52 @@ public Map<String, Object> getKeyset(Iterable<String> propertyPaths, T entity) {
251
256
return keyset ;
252
257
}
253
258
259
+ @ Override
260
+ public boolean isKeysetQualified (Iterable <String > propertyPaths ) {
261
+
262
+ if (propertyPaths .iterator ().hasNext ()) {
263
+ for (String property : propertyPaths ) {
264
+ if (isUnique (property )) {
265
+ return true ;
266
+ }
267
+ }
268
+ }
269
+
270
+ return false ;
271
+ }
272
+
273
+ @ Nullable
274
+ private boolean isUnique (String property ) {
275
+
276
+ Class <?> clazz = getJavaType ();
277
+
278
+ while (clazz != Object .class ) {
279
+
280
+ try {
281
+ Column column = clazz .getDeclaredField (property ).getAnnotation (Column .class );
282
+ if (column != null ) {
283
+ return column .unique ();
284
+ }
285
+ } catch (NoSuchFieldException ex ) {
286
+ // ignore
287
+ }
288
+
289
+ try {
290
+ String getter = "get" + StringUtils .capitalize (property );
291
+ Column column = clazz .getDeclaredMethod (getter ).getAnnotation (Column .class );
292
+ if (column != null ) {
293
+ return column .unique ();
294
+ }
295
+ } catch (NoSuchMethodException ex ) {
296
+ // ignore
297
+ }
298
+
299
+ clazz = clazz .getSuperclass ();
300
+ }
301
+
302
+ return false ;
303
+ }
304
+
254
305
private Function <String , Object > getPropertyValueFunction (Object entity ) {
255
306
256
307
if (entity instanceof Tuple t ) {
0 commit comments