From 4dffef09431a12bb0b793ae422ec44b79d631771 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Thu, 20 Jun 2013 12:06:42 +0200 Subject: [PATCH] DATAJPA-348 - Extending workaround for HHH-6951. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We're now using AnnotationUtils.findAnnotation(…) in case of Hibernate to improve workaround for HHH-6951. Added id type caching as the annotation lookup is potentially expensive. Added integration tests for Hibernate and EclipseLink. --- .../JpaMetamodelEntityInformation.java | 17 ++++- ...odelEntityInformationIntegrationTests.java | 56 +++++++++++++++++ ...odelEntityInformationIntegrationTests.java | 63 +++++++++++++++++-- ...odelEntityInformationIntegrationTests.java | 49 +++++++++++++++ src/test/resources/META-INF/persistence.xml | 32 ++++++++++ src/test/resources/eclipselink.xml | 4 +- src/test/resources/openjpa.xml | 2 +- 7 files changed, 211 insertions(+), 12 deletions(-) create mode 100644 src/test/java/org/springframework/data/jpa/repository/support/EclipseLinkJpaMetamodelEntityInformationIntegrationTests.java create mode 100644 src/test/java/org/springframework/data/jpa/repository/support/OpenJpaMetamodelEntityInformationIntegrationTests.java diff --git a/src/main/java/org/springframework/data/jpa/repository/support/JpaMetamodelEntityInformation.java b/src/main/java/org/springframework/data/jpa/repository/support/JpaMetamodelEntityInformation.java index 5f71a2d4a..8fe4a779e 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/JpaMetamodelEntityInformation.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/JpaMetamodelEntityInformation.java @@ -33,6 +33,7 @@ import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; import org.springframework.beans.NotReadablePropertyException; import org.springframework.beans.NotWritablePropertyException; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; @@ -197,6 +198,7 @@ public class JpaMetamodelEntityInformation extends J private final IdentifiableType type; private final Set> attributes; + private Class idType; @SuppressWarnings("unchecked") public IdMetadata(IdentifiableType source) { @@ -212,13 +214,22 @@ public class JpaMetamodelEntityInformation extends J public Class getType() { + if (idType != null) { + return idType; + } + + Class idType; + try { - return type.getIdType().getJavaType(); + idType = type.getIdType().getJavaType(); } catch (IllegalStateException e) { // see https://hibernate.onjira.com/browse/HHH-6951 - IdClass annotation = type.getJavaType().getAnnotation(IdClass.class); - return annotation == null ? null : annotation.value(); + IdClass annotation = AnnotationUtils.findAnnotation(type.getJavaType(), IdClass.class); + idType = annotation == null ? null : annotation.value(); } + + this.idType = idType; + return idType; } public SingularAttribute getSimpleIdAttribute() { diff --git a/src/test/java/org/springframework/data/jpa/repository/support/EclipseLinkJpaMetamodelEntityInformationIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/support/EclipseLinkJpaMetamodelEntityInformationIntegrationTests.java new file mode 100644 index 000000000..04e7df3a7 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/support/EclipseLinkJpaMetamodelEntityInformationIntegrationTests.java @@ -0,0 +1,56 @@ +/* + * Copyright 2013 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.repository.support; + +import static org.junit.Assert.*; + +import java.io.Serializable; + +import org.junit.Ignore; +import org.junit.Test; +import org.springframework.data.jpa.domain.AbstractPersistable; +import org.springframework.test.context.ContextConfiguration; + +/** + * EclipseLink execution for {@link JpaMetamodelEntityInformationIntegrationTests}. + * + * @author Oliver Gierke + */ +@ContextConfiguration("classpath:eclipselink.xml") +public class EclipseLinkJpaMetamodelEntityInformationIntegrationTests extends + JpaMetamodelEntityInformationIntegrationTests { + + /** + * Re-activate test. Change to check for {@link String} as OpenJpa defaults {@link Serializable}s to {@link String}. + */ + @Test + public void reactivatedDetectsIdTypeForMappedSuperclass() { + JpaEntityInformation information = JpaEntityInformationSupport.getMetadata(AbstractPersistable.class, em); + assertEquals(String.class, information.getIdType()); + } + + /** + * Ignored due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=411231. + */ + @Override + @Ignore + public void findsIdClassOnMappedSuperclass() {} + + @Override + protected String getMetadadataPersitenceUnitName() { + return "metadata_el"; + } +} diff --git a/src/test/java/org/springframework/data/jpa/repository/support/JpaMetamodelEntityInformationIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/support/JpaMetamodelEntityInformationIntegrationTests.java index dbf831b1e..ed9bc501a 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/JpaMetamodelEntityInformationIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/support/JpaMetamodelEntityInformationIntegrationTests.java @@ -20,11 +20,19 @@ import static org.junit.Assert.*; import java.io.Serializable; +import javax.persistence.Access; +import javax.persistence.AccessType; +import javax.persistence.Entity; import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Id; +import javax.persistence.IdClass; import javax.persistence.MappedSuperclass; +import javax.persistence.Persistence; import javax.persistence.PersistenceContext; import javax.persistence.metamodel.Metamodel; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.data.jpa.domain.AbstractPersistable; @@ -37,18 +45,15 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** - * Integration tests for {@link JpaMetamodelEntityInformation}. Has to run with OpenJPA as Hibernate does not implement - * {@link Metamodel#managedType(Class)} correctly (does not consider {@link MappedSuperclass}es correctly). + * Integration tests for {@link JpaMetamodelEntityInformation}. * - * @see https://hibernate.onjira.com/browse/HHH-6896 * @author Oliver Gierke */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration({ "classpath:infrastructure.xml", "classpath:openjpa.xml" }) +@ContextConfiguration({ "classpath:infrastructure.xml" }) public class JpaMetamodelEntityInformationIntegrationTests { - @PersistenceContext - EntityManager em; + @PersistenceContext EntityManager em; @Test public void detectsIdTypeForEntity() { @@ -58,9 +63,14 @@ public class JpaMetamodelEntityInformationIntegrationTests { } /** + * Ignored for Hibernate as it does not implement {@link Metamodel#managedType(Class)} correctly (does not consider + * {@link MappedSuperclass}es correctly). + * + * @see https://hibernate.onjira.com/browse/HHH-6896 * @see DATAJPA-141 */ @Test + @Ignore public void detectsIdTypeForMappedSuperclass() { JpaEntityInformation information = JpaEntityInformationSupport.getMetadata(AbstractPersistable.class, em); @@ -112,4 +122,45 @@ public class JpaMetamodelEntityInformationIntegrationTests { entity.setId(null); assertThat(information.isNew(entity), is(false)); } + + /** + * @see DATAJPA-348 + */ + @Test + public void findsIdClassOnMappedSuperclass() { + + EntityManagerFactory emf = Persistence.createEntityManagerFactory(getMetadadataPersitenceUnitName()); + EntityManager em = emf.createEntityManager(); + + EntityInformation information = new JpaMetamodelEntityInformation( + Sample.class, em.getMetamodel()); + + assertThat(information.getIdType(), is((Object) BaseIdClass.class)); + } + + protected String getMetadadataPersitenceUnitName() { + return "metadata"; + } + + @SuppressWarnings("serial") + public static class BaseIdClass implements Serializable { + + Long id; + Long feedRunId; + } + + @MappedSuperclass + @IdClass(BaseIdClass.class) + @Access(AccessType.FIELD) + public static abstract class Identifiable { + + @Id Long id; + @Id Long feedRunId; + } + + @Entity + @Access(AccessType.FIELD) + public static class Sample extends Identifiable { + + } } diff --git a/src/test/java/org/springframework/data/jpa/repository/support/OpenJpaMetamodelEntityInformationIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/support/OpenJpaMetamodelEntityInformationIntegrationTests.java new file mode 100644 index 000000000..c1a1a6c92 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/support/OpenJpaMetamodelEntityInformationIntegrationTests.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.jpa.repository.support; + +import org.junit.Ignore; +import org.junit.Test; +import org.springframework.test.context.ContextConfiguration; + +/** + * OpenJpa execution for {@link JpaMetamodelEntityInformationIntegrationTests}. + * + * @author Oliver Gierke + */ +@ContextConfiguration("classpath:openjpa.xml") +public class OpenJpaMetamodelEntityInformationIntegrationTests extends JpaMetamodelEntityInformationIntegrationTests { + + /** + * Re-activate test. + */ + @Test + public void reactivatedDetectsIdTypeForMappedSuperclass() { + super.detectsIdTypeForMappedSuperclass(); + } + + /** + * Ignore as it fails with weird {@link NoClassDefFoundError}. + */ + @Override + @Ignore + public void findsIdClassOnMappedSuperclass() {} + + @Override + protected String getMetadadataPersitenceUnitName() { + return "metadata_oj"; + } +} diff --git a/src/test/resources/META-INF/persistence.xml b/src/test/resources/META-INF/persistence.xml index c503b7a85..cfdbee980 100644 --- a/src/test/resources/META-INF/persistence.xml +++ b/src/test/resources/META-INF/persistence.xml @@ -35,4 +35,36 @@ + + + + + org.hibernate.ejb.HibernatePersistence + org.springframework.data.jpa.domain.sample.User + org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformationIntegrationTests$Sample + true + + + + + + org.eclipse.persistence.jpa.PersistenceProvider + org.springframework.data.jpa.domain.sample.User + org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformationIntegrationTests$Sample + true + + + org.apache.openjpa.persistence.PersistenceProviderImpl + org.springframework.data.jpa.domain.sample.User + org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformationIntegrationTests$Sample + true + + + + + + + + + diff --git a/src/test/resources/eclipselink.xml b/src/test/resources/eclipselink.xml index 715112c93..1df967354 100644 --- a/src/test/resources/eclipselink.xml +++ b/src/test/resources/eclipselink.xml @@ -2,8 +2,8 @@ + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> diff --git a/src/test/resources/openjpa.xml b/src/test/resources/openjpa.xml index a9f1abb78..b84c743ad 100644 --- a/src/test/resources/openjpa.xml +++ b/src/test/resources/openjpa.xml @@ -2,7 +2,7 @@