DATAJPA-1105 - Fixed support for nested IdClass with non mapped non primitive type.
When obtaining a multipart id from an entity we have to check for each part of the id if it is another entity. Before this change that check was done be checking if the type is a primitive or wrapper type, which fails to properly classify e.g. String. This caused us to try to get an id from a String instance which of course failed because String is not a managed type. Now we make the necessary distinction based on JpaMetamodel.isJpaManaged(type). Changes in the persistence.xml beyond adding entities for tests are required to make the tests work again with EclipseLink. This didn't cause problems in the past because all tests that actually access the database and use the changed persistence context are disabled for EclipseLink. The new test had to be get disabled for EclipseLink though, due to another bug in EclipseLink which prevents the usage of inner classes in @IdClass annotations. See also: https://bugs.eclipse.org/bugs/show_bug.cgi?id=531528 Original pull request: #251.
This commit is contained in:
committed by
Oliver Gierke
parent
65f0020636
commit
63ceb6da71
@@ -35,10 +35,10 @@ import javax.persistence.metamodel.Type.PersistenceType;
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
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}
|
||||
@@ -48,6 +48,7 @@ import org.springframework.util.ClassUtils;
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
public class JpaMetamodelEntityInformation<T, ID> extends JpaEntityInformationSupport<T, ID> {
|
||||
|
||||
@@ -319,10 +320,12 @@ public class JpaMetamodelEntityInformation<T, ID> extends JpaEntityInformationSu
|
||||
extends DirectFieldAccessFallbackBeanWrapper {
|
||||
|
||||
private final Metamodel metamodel;
|
||||
private final JpaMetamodel jpaMetamodel;
|
||||
|
||||
IdentifierDerivingDirectFieldAccessFallbackBeanWrapper(Class<?> type, Metamodel metamodel) {
|
||||
super(type);
|
||||
this.metamodel = metamodel;
|
||||
this.jpaMetamodel = new JpaMetamodel(metamodel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -374,7 +377,7 @@ public class JpaMetamodelEntityInformation<T, ID> extends JpaEntityInformationSu
|
||||
|
||||
Class<? extends Object> idPropertyValueType = idPropertyValue.getClass();
|
||||
|
||||
if (ClassUtils.isPrimitiveOrWrapper(idPropertyValueType)) {
|
||||
if (!jpaMetamodel.isJpaManaged(idPropertyValueType)) {
|
||||
return idPropertyValue;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
* EclipseLink execution for {@link JpaMetamodelEntityInformationIntegrationTests}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
@ContextConfiguration("classpath:eclipselink.xml")
|
||||
public class EclipseLinkJpaMetamodelEntityInformationIntegrationTests
|
||||
@@ -69,6 +70,14 @@ public class EclipseLinkJpaMetamodelEntityInformationIntegrationTests
|
||||
super.detectsVersionPropertyOnMappedSuperClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignored due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=531528 EclipseLink doesn't support
|
||||
* {@link javax.persistence.IdClass} referencing inner classes.
|
||||
*/
|
||||
@Override
|
||||
@Ignore
|
||||
public void correctlyDeterminesIdValueForNestedIdClassesWithNonPrimitiveNonManagedType() {}
|
||||
|
||||
@Override
|
||||
protected String getMetadadataPersitenceUnitName() {
|
||||
return "metadata_el";
|
||||
|
||||
@@ -19,6 +19,8 @@ import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.*;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Date;
|
||||
@@ -42,6 +44,7 @@ import org.springframework.test.util.ReflectionTestUtils;
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration({ "classpath:infrastructure.xml" })
|
||||
@@ -258,6 +261,26 @@ public class JpaMetamodelEntityInformationIntegrationTests {
|
||||
assertThat(ReflectionTestUtils.getField(information, "versionAttribute"), is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test // DATAJPA-1105
|
||||
public void correctlyDeterminesIdValueForNestedIdClassesWithNonPrimitiveNonManagedType() {
|
||||
|
||||
EntityManagerFactory emf = Persistence.createEntityManagerFactory(getMetadadataPersitenceUnitName());
|
||||
EntityManager em = emf.createEntityManager();
|
||||
|
||||
JpaEntityInformation<EntityWithNestedIdClass, ?> information = getEntityInformation(EntityWithNestedIdClass.class,
|
||||
em);
|
||||
|
||||
EntityWithNestedIdClass entity = new EntityWithNestedIdClass();
|
||||
entity.id = 23L;
|
||||
entity.reference = new EntityWithIdClass();
|
||||
entity.reference.id1 = "one";
|
||||
entity.reference.id2 = "two";
|
||||
|
||||
Object id = information.getId(entity);
|
||||
|
||||
assertThat(id, is(notNullValue()));
|
||||
}
|
||||
|
||||
protected String getMetadadataPersitenceUnitName() {
|
||||
return "metadata";
|
||||
}
|
||||
@@ -283,4 +306,36 @@ public class JpaMetamodelEntityInformationIntegrationTests {
|
||||
public static class Sample extends Identifiable {
|
||||
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Access(AccessType.FIELD)
|
||||
@IdClass(EntityWithNestedIdClassPK.class)
|
||||
public static class EntityWithNestedIdClass {
|
||||
|
||||
@Id Long id;
|
||||
@Id @ManyToOne private EntityWithIdClass reference;
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Access(AccessType.FIELD)
|
||||
@IdClass(EntityWithIdClassPK.class)
|
||||
public static class EntityWithIdClass {
|
||||
|
||||
@Id String id1;
|
||||
@Id String id2;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class EntityWithIdClassPK implements Serializable {
|
||||
|
||||
String id1;
|
||||
String id2;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class EntityWithNestedIdClassPK implements Serializable {
|
||||
|
||||
Long id;
|
||||
EntityWithIdClassPK reference;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,12 @@
|
||||
<class>org.springframework.data.jpa.domain.sample.MailUser</class>
|
||||
<class>org.springframework.data.jpa.domain.sample.User</class>
|
||||
<class>org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformationIntegrationTests$Sample</class>
|
||||
<class>
|
||||
org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformationIntegrationTests$EntityWithNestedIdClass
|
||||
</class>
|
||||
<class>
|
||||
org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformationIntegrationTests$EntityWithIdClass
|
||||
</class>
|
||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||
<properties>
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
|
||||
@@ -107,8 +113,22 @@
|
||||
<class>org.springframework.data.jpa.domain.sample.MailUser</class>
|
||||
<class>org.springframework.data.jpa.domain.sample.User</class>
|
||||
<class>org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformationIntegrationTests$Sample</class>
|
||||
<class>
|
||||
org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformationIntegrationTests$EntityWithNestedIdClass
|
||||
</class>
|
||||
<class>
|
||||
org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformationIntegrationTests$EntityWithIdClass
|
||||
</class>
|
||||
<class>org.springframework.data.jpa.domain.sample.Dummy</class>
|
||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||
<properties>
|
||||
<property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
|
||||
<property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:test"/>
|
||||
<property name="javax.persistence.jdbc.user" value="sa"/>
|
||||
<property name="javax.persistence.jdbc.password" value=""/>
|
||||
<property name="eclipselink.ddl-generation" value="create-tables"/>
|
||||
<property name="eclipselink.ddl-generation.output-mode" value="database"/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
<persistence-unit name="metadata_oj">
|
||||
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
|
||||
|
||||
Reference in New Issue
Block a user