DATAJPA-1416 - Unwrap proxies in JpaMetamodelEntityInformation.

Previously, when JpaMetamodelEntityInfortmation operated on a proxy class it failed to detect it as an entity. This problem is now solved by unwrapping the potential proxy before passing it into JpaMetamodelEntityInformation.

Original pull request: #293.
This commit is contained in:
Jens Schauder
2018-09-04 14:08:47 +02:00
committed by Oliver Gierke
parent 64062aa559
commit 485bf50bc1
5 changed files with 91 additions and 6 deletions

View File

@@ -39,6 +39,7 @@ import org.springframework.data.jpa.util.JpaMetamodel;
import org.springframework.data.util.DirectFieldAccessFallbackBeanWrapper;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* Implementation of {@link org.springframework.data.repository.core.EntityInformation} that uses JPA {@link Metamodel}
@@ -343,8 +344,8 @@ public class JpaMetamodelEntityInformation<T, ID> extends JpaEntityInformationSu
// Derive the identifier from the nested entity that is part of the composite key.
@SuppressWarnings("rawtypes")
JpaMetamodelEntityInformation nestedEntityInformation = new JpaMetamodelEntityInformation(value.getClass(),
this.metamodel);
JpaMetamodelEntityInformation nestedEntityInformation = new JpaMetamodelEntityInformation(
ClassUtils.getUserClass(value), this.metamodel);
if (!nestedEntityInformation.getJavaType().isAnnotationPresent(IdClass.class)) {
@@ -413,7 +414,7 @@ public class JpaMetamodelEntityInformation<T, ID> extends JpaEntityInformationSu
}
try {
ManagedType<? extends Object> managedType = this.metamodel.managedType(value.getClass());
ManagedType<? extends Object> managedType = this.metamodel.managedType(ClassUtils.getUserClass(value));
return managedType != null && managedType.getPersistenceType() == PersistenceType.ENTITY;
} catch (IllegalArgumentException iae) {
// no mapped type

View File

@@ -0,0 +1,45 @@
package org.springframework.data.jpa.domain.sample;
import lombok.Data;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.ManyToOne;
/**
* Sample class for integration testing
* {@link org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation}.
*
* @author Jens Schauder
*/
@Entity
@IdClass(SampleWithIdClassIncludingEntity.SampleWithIdClassPK.class)
@Data
public class SampleWithIdClassIncludingEntity {
@Id Long first;
@ManyToOne @Id OtherEntity second;
@Data
@SuppressWarnings("serial")
public static class SampleWithIdClassPK implements Serializable {
Long first;
Long second;
}
@Entity
@Data
public static class OtherEntity {
@Id Long otherId;
}
/**
* This class emulates a proxy at is returned from Hibernate.
*/
public static class OtherEntity$$PsudoProxy extends OtherEntity {}
}

View File

@@ -71,13 +71,28 @@ public class EclipseLinkJpaMetamodelEntityInformationIntegrationTests
}
/**
* Ignored due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=531528 EclipseLink doesn't support
* {@link javax.persistence.IdClass} referencing inner classes.
* This test fails due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=531528 IdentifiableType.hasSingleIdAttribute()
* returns true when IdClass references an inner class. This bug is supposedly fixed, but the test still fails.
*/
@Ignore
@Test
@Override
public void correctlyDeterminesIdValueForNestedIdClassesWithNonPrimitiveNonManagedType() {}
public void correctlyDeterminesIdValueForNestedIdClassesWithNonPrimitiveNonManagedType() {
super.correctlyDeterminesIdValueForNestedIdClassesWithNonPrimitiveNonManagedType();
}
/**
* This test fails due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=531528 IdentifiableType.hasSingleIdAttribute()
* returns true when IdClass references an inner class. This bug is supposedly fixed, but the test still fails.
*/
@Ignore
@Test
@Override
public void proxiedIdClassElement() {
super.proxiedIdClassElement();
}
@Override
protected String getMetadadataPersitenceUnitName() {

View File

@@ -281,6 +281,28 @@ public class JpaMetamodelEntityInformationIntegrationTests {
assertThat(id, is(notNullValue()));
}
@Test // DATAJPA-1416
public void proxiedIdClassElement() {
JpaEntityInformation<SampleWithIdClassIncludingEntity, ?> information = getEntityInformation(
SampleWithIdClassIncludingEntity.class, em);
SampleWithIdClassIncludingEntity entity = new SampleWithIdClassIncludingEntity();
entity.setFirst(23L);
SampleWithIdClassIncludingEntity.OtherEntity$$PsudoProxy inner = new SampleWithIdClassIncludingEntity.OtherEntity$$PsudoProxy();
inner.setOtherId(42L);
entity.setSecond(inner);
Object id = information.getId(entity);
assertTrue(id instanceof SampleWithIdClassIncludingEntity.SampleWithIdClassPK);
SampleWithIdClassIncludingEntity.SampleWithIdClassPK pk = (SampleWithIdClassIncludingEntity.SampleWithIdClassPK) id;
assertThat(pk.getFirst(), equalTo(23L));
assertThat(pk.getSecond(), equalTo(42L));
}
protected String getMetadadataPersitenceUnitName() {
return "metadata";
}

View File

@@ -42,6 +42,8 @@
<class>org.springframework.data.jpa.domain.sample.User</class>
<class>org.springframework.data.jpa.domain.sample.VersionedUser</class>
<class>org.springframework.data.jpa.domain.sample.Dummy</class>
<class>org.springframework.data.jpa.domain.sample.SampleWithIdClassIncludingEntity</class>
<class>org.springframework.data.jpa.domain.sample.SampleWithIdClassIncludingEntity$OtherEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>
<persistence-unit name="querydsl">