diff --git a/pom.xml b/pom.xml index 8576363d34..dc9cdf4353 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-commons - 3.3.0-SNAPSHOT + 3.3.x-3038-SNAPSHOT Spring Data Core Core Spring concepts underpinning every Spring Data module. diff --git a/src/main/java/org/springframework/data/mapping/Parameter.java b/src/main/java/org/springframework/data/mapping/Parameter.java index 091370cd52..14d53a6cfb 100644 --- a/src/main/java/org/springframework/data/mapping/Parameter.java +++ b/src/main/java/org/springframework/data/mapping/Parameter.java @@ -24,6 +24,7 @@ import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; /** @@ -31,6 +32,7 @@ * * @param the type of the parameter * @author Oliver Gierke + * @author Christoph Strobl */ public class Parameter> { @@ -72,7 +74,7 @@ public Parameter(@Nullable String name, TypeInformation type, Annotation[] an } Class owningType = entity.getType(); - return owningType.isMemberClass() && type.getType().equals(owningType.getEnclosingClass()); + return ClassUtils.isInnerClass(owningType) && type.getType().equals(owningType.getEnclosingClass()); }); this.hasSpelExpression = Lazy.of(() -> StringUtils.hasText(getSpelExpression())); diff --git a/src/test/java/org/springframework/data/mapping/ParameterUnitTests.java b/src/test/java/org/springframework/data/mapping/ParameterUnitTests.java index eb0b4c67ac..3465c8f045 100755 --- a/src/test/java/org/springframework/data/mapping/ParameterUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/ParameterUnitTests.java @@ -16,19 +16,27 @@ package org.springframework.data.mapping; import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; import java.lang.annotation.Annotation; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.mapping.ParameterUnitTests.IFace.ClassMember; +import org.springframework.data.mapping.ParameterUnitTests.IFace.RecordMember; +import org.springframework.data.mapping.ParameterUnitTests.StaticType.NonStaticInner; +import org.springframework.data.mapping.ParameterUnitTests.StaticType.RecordInner; +import org.springframework.data.mapping.ParameterUnitTests.StaticType.StaticInner; import org.springframework.data.util.TypeInformation; /** * Unit tests for {@link Parameter}. * * @author Oliver Gierke + * @author Christoph Strobl */ @ExtendWith(MockitoExtension.class) class ParameterUnitTests

> { @@ -87,4 +95,81 @@ void twoParametersWithDifferenTypeAreNotEqual() { assertThat(left).isNotEqualTo(right); } + + @Test // GH-3038 + void shouldNotConsiderRecordTypeOfInterfaceEnclosingClassParameter() { + + PersistentEntity pe = Mockito.mock(PersistentEntity.class); + when(pe.getType()).thenReturn(RecordMember.class); + + Parameter iFace = new Parameter("iFace", TypeInformation.of(IFace.class), annotations, pe); + assertThat(iFace.isEnclosingClassParameter()).isFalse(); + } + + @Test // GH-3038 + void shouldNotConsiderMemberTypeOfInterfaceEnclosingClassParameter() { + + PersistentEntity pe = Mockito.mock(PersistentEntity.class); + when(pe.getType()).thenReturn(ClassMember.class); + + Parameter iFace = new Parameter("iFace", TypeInformation.of(IFace.class), annotations, pe); + assertThat(iFace.isEnclosingClassParameter()).isFalse(); + } + + @Test // GH-3038 + void shouldConsiderMemberTypeOfClassEnclosingClassParameter() { + + PersistentEntity pe = Mockito.mock(PersistentEntity.class); + when(pe.getType()).thenReturn(NonStaticInner.class); + + Parameter iFace = new Parameter("outer", TypeInformation.of(StaticType.class), + annotations, pe); + assertThat(iFace.isEnclosingClassParameter()).isTrue(); + } + + @Test // GH-3038 + void shouldNotConsiderStaticMemberTypeOfClassEnclosingClassParameter() { + + PersistentEntity pe = Mockito.mock(PersistentEntity.class); + when(pe.getType()).thenReturn(StaticInner.class); + + Parameter iFace = new Parameter("outer", TypeInformation.of(StaticType.class), + annotations, pe); + assertThat(iFace.isEnclosingClassParameter()).isFalse(); + } + + @Test // GH-3038 + void shouldNotConsiderRecordMemberTypeOfClassEnclosingClassParameter() { + + PersistentEntity pe = Mockito.mock(PersistentEntity.class); + when(pe.getType()).thenReturn(RecordInner.class); + + Parameter iFace = new Parameter("outer", TypeInformation.of(StaticType.class), + annotations, pe); + assertThat(iFace.isEnclosingClassParameter()).isFalse(); + } + + interface IFace { + + record RecordMember(IFace iFace) { + } + + class ClassMember { + ClassMember(IFace iface) {} + } + } + + static class StaticType { + + class NonStaticInner { + NonStaticInner(StaticType outer) {} + } + + static class StaticInner { + StaticInner(StaticType outer) {} + } + + record RecordInner(StaticType outer) { + } + } }