From bc4a39aa9b2ec63b59eed4b70cef0d0fe573bced Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Wed, 17 Jun 2015 12:47:07 +0200 Subject: [PATCH] DATAJPA-633 - Back-ported detection of targetEntity attribute. Back port of the fix for DATAJPA-664 to make sure interface types can be used for associations. This broke in the Dijkstra/Evans train due to the fix in DATACMNS-479 and now most recently pops up in the use of Maps with interfaces as values. Related tickets: DATAJPA-664, DATACMNS-479. --- .../mapping/JpaPersistentPropertyImpl.java | 48 ++++++++++++++++++- .../JpaPersistentPropertyImplUnitTests.java | 34 ++++++++++++- 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/springframework/data/jpa/mapping/JpaPersistentPropertyImpl.java b/src/main/java/org/springframework/data/jpa/mapping/JpaPersistentPropertyImpl.java index a21c041cb..dd2e29a68 100644 --- a/src/main/java/org/springframework/data/jpa/mapping/JpaPersistentPropertyImpl.java +++ b/src/main/java/org/springframework/data/jpa/mapping/JpaPersistentPropertyImpl.java @@ -34,10 +34,13 @@ import javax.persistence.OneToOne; import javax.persistence.Transient; import javax.persistence.metamodel.Metamodel; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty; import org.springframework.data.mapping.model.SimpleTypeHolder; +import org.springframework.data.util.ClassTypeInformation; +import org.springframework.data.util.TypeInformation; import org.springframework.util.Assert; /** @@ -46,8 +49,8 @@ import org.springframework.util.Assert; * @author Oliver Gierke * @since 1.3 */ -class JpaPersistentPropertyImpl extends AnnotationBasedPersistentProperty implements - JpaPersistentProperty { +class JpaPersistentPropertyImpl extends AnnotationBasedPersistentProperty + implements JpaPersistentProperty { private static final Collection> ASSOCIATION_ANNOTATIONS; private static final Collection> ID_ANNOTATIONS; @@ -71,6 +74,7 @@ class JpaPersistentPropertyImpl extends AnnotationBasedPersistentProperty associationTargetType; /** * Creates a new {@link JpaPersistentPropertyImpl} @@ -89,6 +93,26 @@ class JpaPersistentPropertyImpl extends AnnotationBasedPersistentProperty getActualType() { + return associationTargetType == null ? super.getActualType() : associationTargetType.getType(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mapping.model.AbstractPersistentProperty#getPersistentEntityType() + */ + @Override + public Iterable> getPersistentEntityType() { + return associationTargetType == null ? super.getPersistentEntityType() + : Collections.singleton(associationTargetType); } /* @@ -159,4 +183,24 @@ class JpaPersistentPropertyImpl extends AnnotationBasedPersistentProperty createAssociation() { return new Association(this, null); } + + /** + * Inspects the association annotations on the property and returns the target entity type if specified. + * + * @return + */ + private TypeInformation detectAssociationTargetType() { + + for (Class associationAnnotation : ASSOCIATION_ANNOTATIONS) { + + Annotation annotation = findAnnotation(associationAnnotation); + Object targetEntity = AnnotationUtils.getValue(annotation, "targetEntity"); + + if (targetEntity != null && !void.class.equals(targetEntity)) { + return ClassTypeInformation.from((Class) targetEntity); + } + } + + return null; + } } diff --git a/src/test/java/org/springframework/data/jpa/mapping/JpaPersistentPropertyImplUnitTests.java b/src/test/java/org/springframework/data/jpa/mapping/JpaPersistentPropertyImplUnitTests.java index 32c4b0930..b4df68bac 100644 --- a/src/test/java/org/springframework/data/jpa/mapping/JpaPersistentPropertyImplUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/mapping/JpaPersistentPropertyImplUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 the original author or authors. + * Copyright 2013-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,11 +15,12 @@ */ package org.springframework.data.jpa.mapping; -import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import javax.persistence.Embeddable; import javax.persistence.Embedded; +import javax.persistence.ManyToOne; import javax.persistence.OneToOne; import javax.persistence.Transient; import javax.persistence.metamodel.Metamodel; @@ -92,6 +93,24 @@ public class JpaPersistentPropertyImplUnitTests { assertThat(entity.getPersistentProperty("embedded").isAssociation(), is(true)); } + /** + * @see DATAJPA-664 + */ + @Test + public void considersTargetEntityTypeForPropertyType() { + + JpaPersistentProperty property = getProperty(SpecializedAssociation.class, "api"); + + assertThat(property.getType(), is(typeCompatibleWith(Api.class))); + assertThat(property.getActualType(), is(typeCompatibleWith(Implementation.class))); + } + + private JpaPersistentProperty getProperty(Class ownerType, String propertyName) { + + JpaPersistentEntity entity = context.getPersistentEntity(ownerType); + return entity.getPersistentProperty(propertyName); + } + static class Sample { @OneToOne Sample other; @@ -108,4 +127,15 @@ public class JpaPersistentPropertyImplUnitTests { static class SampleEmbedded { } + + // DATAJPA-664 + + static class SpecializedAssociation { + + @ManyToOne(targetEntity = Implementation.class) Api api; + } + + static interface Api {} + + static class Implementation {} }