From cd6d7b6e5b207f500a984ead2fce2ee6504dde6a Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Mon, 24 Nov 2014 13:32:44 +0100 Subject: [PATCH] DATAJPA-630 - Add IdentifierAccessor implementation that avoids proxy resolution for id lookups. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now customize the IdentifierAccessor returned from JpaPersistentEntity.getIdentifierAccessor(…) to allow the identifier lookup use persistence provider specific means. This is needed to make sure we lookup identifiers for proxies correctly for which a field value lookup would not succeed (as the providers do not pre-populate the identifier field). --- .../mapping/JpaMetamodelMappingContext.java | 8 +- .../jpa/mapping/JpaPersistentEntityImpl.java | 69 ++++- .../utils => provider}/JpaClassUtils.java | 22 +- .../jpa/provider/PersistenceProvider.java | 284 ++++++++++++++++++ .../data/jpa/provider/ProxyIdAccessor.java | 41 +++ .../query => provider}/QueryExtractor.java | 2 +- .../query/JpaQueryLookupStrategy.java | 1 + .../jpa/repository/query/JpaQueryMethod.java | 1 + .../data/jpa/repository/query/NamedQuery.java | 1 + .../support/JpaEntityInformationSupport.java | 2 +- .../support/JpaRepositoryFactory.java | 5 +- .../support/PersistenceProvider.java | 182 ----------- .../data/jpa/repository/support/Querydsl.java | 1 + .../support/SimpleJpaRepository.java | 3 +- .../data/jpa/domain/sample/Category.java | 30 ++ .../data/jpa/domain/sample/Product.java | 15 + ...tamodelMappingContextIntegrationTests.java | 73 ++++- .../JpaPersistentPropertyImplUnitTests.java | 4 +- .../PersistenceProviderIntegrationTests.java | 98 ++++++ .../PersistenceProviderUnitTests.java} | 32 +- ....java => CrudMethodMetadataUnitTests.java} | 3 +- .../JavaConfigUserRepositoryTests.java | 3 +- .../query/AbstractJpaQueryTests.java | 3 +- .../JpaQueryLookupStrategyUnitTests.java | 1 + .../query/JpaQueryMethodUnitTests.java | 1 + .../repository/query/NamedQueryUnitTests.java | 1 + .../PartTreeJpaQueryIntegrationTests.java | 2 +- .../query/SimpleJpaQueryUnitTests.java | 1 + .../repository/sample/CategoryRepository.java | 24 ++ .../repository/sample/ProductRepository.java | 26 ++ ...odelEntityInformationIntegrationTests.java | 7 +- .../EclipseLinkProxyIdAccessorTests.java | 40 +++ .../JpaEntityInformationSupportUnitTests.java | 2 +- ...odelEntityInformationIntegrationTests.java | 24 +- .../JpaRepositoryFactoryUnitTests.java | 14 +- .../support/OpenJpaProxyIdAccessorTests.java | 32 ++ .../support/SimpleJpaRepositoryUnitTests.java | 2 + src/test/resources/META-INF/persistence.xml | 2 + src/test/resources/META-INF/persistence2.xml | 16 +- template.mf | 2 +- 40 files changed, 815 insertions(+), 265 deletions(-) rename src/main/java/org/springframework/data/jpa/{repository/utils => provider}/JpaClassUtils.java (67%) create mode 100644 src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java create mode 100644 src/main/java/org/springframework/data/jpa/provider/ProxyIdAccessor.java rename src/main/java/org/springframework/data/jpa/{repository/query => provider}/QueryExtractor.java (96%) delete mode 100644 src/main/java/org/springframework/data/jpa/repository/support/PersistenceProvider.java create mode 100644 src/test/java/org/springframework/data/jpa/domain/sample/Category.java create mode 100644 src/test/java/org/springframework/data/jpa/domain/sample/Product.java create mode 100644 src/test/java/org/springframework/data/jpa/provider/PersistenceProviderIntegrationTests.java rename src/test/java/org/springframework/data/jpa/{repository/support/PersistenceProviderTests.java => provider/PersistenceProviderUnitTests.java} (82%) rename src/test/java/org/springframework/data/jpa/repository/{CrudMethodMetadataIntegrationTests.java => CrudMethodMetadataUnitTests.java} (97%) create mode 100644 src/test/java/org/springframework/data/jpa/repository/sample/CategoryRepository.java create mode 100644 src/test/java/org/springframework/data/jpa/repository/sample/ProductRepository.java create mode 100644 src/test/java/org/springframework/data/jpa/repository/support/EclipseLinkProxyIdAccessorTests.java create mode 100644 src/test/java/org/springframework/data/jpa/repository/support/OpenJpaProxyIdAccessorTests.java diff --git a/src/main/java/org/springframework/data/jpa/mapping/JpaMetamodelMappingContext.java b/src/main/java/org/springframework/data/jpa/mapping/JpaMetamodelMappingContext.java index e0d825330..a6198fc35 100644 --- a/src/main/java/org/springframework/data/jpa/mapping/JpaMetamodelMappingContext.java +++ b/src/main/java/org/springframework/data/jpa/mapping/JpaMetamodelMappingContext.java @@ -17,7 +17,6 @@ package org.springframework.data.jpa.mapping; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; -import java.util.Collections; import java.util.Set; import javax.persistence.metamodel.ManagedType; @@ -49,11 +48,8 @@ public class JpaMetamodelMappingContext extends Assert.notNull(models, "JPA metamodel must not be null!"); Assert.notEmpty(models, "At least one JPA metamodel must be present!"); - this.models = models; - } - public JpaMetamodelMappingContext(Metamodel model) { - this(Collections.singleton(model)); + this.models = models; } /* @@ -62,7 +58,7 @@ public class JpaMetamodelMappingContext extends */ @Override protected JpaPersistentEntityImpl createPersistentEntity(TypeInformation typeInformation) { - return new JpaPersistentEntityImpl(typeInformation, null); + return new JpaPersistentEntityImpl(typeInformation, getMetamodelFor(typeInformation.getType())); } /* diff --git a/src/main/java/org/springframework/data/jpa/mapping/JpaPersistentEntityImpl.java b/src/main/java/org/springframework/data/jpa/mapping/JpaPersistentEntityImpl.java index 4e133b7c8..7f2b2489f 100644 --- a/src/main/java/org/springframework/data/jpa/mapping/JpaPersistentEntityImpl.java +++ b/src/main/java/org/springframework/data/jpa/mapping/JpaPersistentEntityImpl.java @@ -17,8 +17,15 @@ package org.springframework.data.jpa.mapping; import java.util.Comparator; +import javax.persistence.metamodel.Metamodel; + +import org.springframework.data.jpa.provider.PersistenceProvider; +import org.springframework.data.jpa.provider.ProxyIdAccessor; +import org.springframework.data.mapping.IdentifierAccessor; import org.springframework.data.mapping.model.BasicPersistentEntity; +import org.springframework.data.mapping.model.IdPropertyIdentifierAccessor; import org.springframework.data.util.TypeInformation; +import org.springframework.util.Assert; /** * Implementation of {@link JpaPersistentEntity}. @@ -29,14 +36,20 @@ import org.springframework.data.util.TypeInformation; class JpaPersistentEntityImpl extends BasicPersistentEntity implements JpaPersistentEntity { + private final ProxyIdAccessor proxyIdAccessor; + /** * Creates a new {@link JpaPersistentEntityImpl} using the given {@link TypeInformation} and {@link Comparator}. * * @param information must not be {@literal null}. - * @param comparator must not be {@literal null}. + * @param metamodel must not be {@literal null}. */ - public JpaPersistentEntityImpl(TypeInformation information, Comparator comparator) { - super(information, comparator); + public JpaPersistentEntityImpl(TypeInformation information, Metamodel metamodel) { + + super(information, null); + + Assert.notNull(metamodel, "Metamodel must not be null!"); + this.proxyIdAccessor = PersistenceProvider.fromMetamodel(metamodel); } /* @@ -47,4 +60,54 @@ class JpaPersistentEntityImpl extends BasicPersistentEntity entity, Object bean, ProxyIdAccessor proxyIdAccessor) { + + super(entity, bean); + + Assert.notNull(proxyIdAccessor, "Proxy identifier accessor must not be null!"); + + this.proxyIdAccessor = proxyIdAccessor; + this.bean = bean; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mapping.IdentifierAccessor#getIdentifier() + */ + @Override + public Object getIdentifier() { + return proxyIdAccessor.shouldUseAccessorFor(bean) ? proxyIdAccessor.getIdentifierFrom(bean) : super + .getIdentifier(); + } + } } diff --git a/src/main/java/org/springframework/data/jpa/repository/utils/JpaClassUtils.java b/src/main/java/org/springframework/data/jpa/provider/JpaClassUtils.java similarity index 67% rename from src/main/java/org/springframework/data/jpa/repository/utils/JpaClassUtils.java rename to src/main/java/org/springframework/data/jpa/provider/JpaClassUtils.java index fd91caf90..4f0eeaa64 100644 --- a/src/main/java/org/springframework/data/jpa/repository/utils/JpaClassUtils.java +++ b/src/main/java/org/springframework/data/jpa/provider/JpaClassUtils.java @@ -13,9 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.jpa.repository.utils; +package org.springframework.data.jpa.provider; import javax.persistence.EntityManager; +import javax.persistence.metamodel.Metamodel; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -25,7 +26,7 @@ import org.springframework.util.ClassUtils; * * @author Oliver Gierke */ -public abstract class JpaClassUtils { +abstract class JpaClassUtils { /** * Private constructor to prevent instantiation. @@ -42,16 +43,21 @@ public abstract class JpaClassUtils { * @return */ public static boolean isEntityManagerOfType(EntityManager em, String type) { + return isOfType(em, type, em.getDelegate().getClass().getClassLoader()); + } - Assert.notNull(em, "EntityManager must not be null!"); - Assert.hasText(type, "EntityManager type must not be null!"); + public static boolean isMetamodelOfType(Metamodel metamodel, String type) { + return isOfType(metamodel, type, metamodel.getClass().getClassLoader()); + } + + private static boolean isOfType(Object source, String typeName, ClassLoader classLoader) { + + Assert.notNull(source, "Source instance must not be null!"); + Assert.hasText(typeName, "Target type name must not be null or empty!"); try { - ClassLoader loader = em.getDelegate().getClass().getClassLoader(); - Class emType = ClassUtils.forName(type, loader); - - emType.cast(em); + ClassUtils.forName(typeName, classLoader).cast(source); return true; } catch (Exception e) { diff --git a/src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java b/src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java new file mode 100644 index 000000000..dd1177047 --- /dev/null +++ b/src/main/java/org/springframework/data/jpa/provider/PersistenceProvider.java @@ -0,0 +1,284 @@ +/* + * Copyright 2008-2014 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.provider; + +import static org.springframework.data.jpa.provider.JpaClassUtils.*; +import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.*; + +import java.util.Arrays; +import java.util.Collections; + +import javax.persistence.EntityManager; +import javax.persistence.Query; +import javax.persistence.metamodel.Metamodel; + +import org.apache.openjpa.enhance.PersistenceCapable; +import org.apache.openjpa.persistence.OpenJPAQuery; +import org.eclipse.persistence.jpa.JpaQuery; +import org.hibernate.ejb.HibernateQuery; +import org.hibernate.proxy.HibernateProxy; +import org.springframework.util.Assert; + +/** + * Enumeration representing persistence providers to be used. + * + * @author Oliver Gierke + * @author Thomas Darimont + */ +public enum PersistenceProvider implements QueryExtractor, ProxyIdAccessor { + + /** + * Hibernate persistence provider. + *

+ * Since Hibernate 4.3 the location of the HibernateEntityManager moved to the org.hibernate.jpa package. In order to + * support both locations we interpret both classnames as a Hibernate {@code PersistenceProvider}. + * + * @see DATAJPA-444 + */ + HIBERNATE(// + Arrays.asList(HIBERNATE43_ENTITY_MANAGER_INTERFACE, HIBERNATE_ENTITY_MANAGER_INTERFACE), // + Arrays.asList(HIBERNATE43_JPA_METAMODEL_TYPE, HIBERNATE_JPA_METAMODEL_TYPE)) { + + public String extractQueryString(Query query) { + return ((HibernateQuery) query).getHibernateQuery().getQueryString(); + } + + /** + * Return custom placeholder ({@code *}) as Hibernate does create invalid queries for count queries for objects with + * compound keys. + * + * @see HHH-4044 + * @see HHH-3096 + */ + @Override + public String getCountQueryPlaceholder() { + return "*"; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.support.ProxyIdAccessor#isProxy(java.lang.Object) + */ + @Override + public boolean shouldUseAccessorFor(Object entity) { + return entity instanceof HibernateProxy; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.support.ProxyIdAccessor#getIdentifierFrom(java.lang.Object) + */ + @Override + public Object getIdentifierFrom(Object entity) { + return ((HibernateProxy) entity).getHibernateLazyInitializer().getIdentifier(); + } + }, + + /** + * EclipseLink persistence provider. + */ + ECLIPSELINK(Collections.singleton(ECLIPSELINK_ENTITY_MANAGER_INTERFACE), Collections + .singleton(ECLIPSELINK_JPA_METAMODEL_TYPE)) { + + public String extractQueryString(Query query) { + return ((JpaQuery) query).getDatabaseQuery().getJPQLString(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.support.ProxyIdAccessor#isProxy(java.lang.Object) + */ + @Override + public boolean shouldUseAccessorFor(Object entity) { + return false; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.support.ProxyIdAccessor#getIdentifierFrom(java.lang.Object) + */ + @Override + public Object getIdentifierFrom(Object entity) { + return null; + } + }, + + /** + * OpenJpa persistence provider. + */ + OPEN_JPA(Collections.singleton(OPENJPA_ENTITY_MANAGER_INTERFACE), Collections.singleton(OPENJPA_JPA_METAMODEL_TYPE)) { + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.query.QueryExtractor#extractQueryString(javax.persistence.Query) + */ + @Override + public String extractQueryString(Query query) { + return ((OpenJPAQuery) query).getQueryString(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.support.ProxyIdAccessor#isProxy(java.lang.Object) + */ + @Override + public boolean shouldUseAccessorFor(Object entity) { + return entity instanceof PersistenceCapable; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.support.ProxyIdAccessor#getIdentifierFrom(java.lang.Object) + */ + @Override + public Object getIdentifierFrom(Object entity) { + return ((PersistenceCapable) entity).pcFetchObjectId(); + } + }, + + /** + * Unknown special provider. Use standard JPA. + */ + GENERIC_JPA(Collections.singleton(GENERIC_JPA_ENTITY_MANAGER_INTERFACE), Collections. emptySet()) { + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.query.QueryExtractor#extractQueryString(javax.persistence.Query) + */ + @Override + public String extractQueryString(Query query) { + return null; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.support.PersistenceProvider#canExtractQuery() + */ + @Override + public boolean canExtractQuery() { + return false; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.support.ProxyIdAccessor#isProxy(java.lang.Object) + */ + @Override + public boolean shouldUseAccessorFor(Object entity) { + return false; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jpa.repository.support.ProxyIdAccessor#getIdentifierFrom(java.lang.Object) + */ + @Override + public Object getIdentifierFrom(Object entity) { + return null; + } + }; + + /** + * Holds the PersistenceProvider specific interface names. + * + * @author Thomas Darimont + */ + static interface Constants { + + String GENERIC_JPA_ENTITY_MANAGER_INTERFACE = "javax.persistence.EntityManager"; + String OPENJPA_ENTITY_MANAGER_INTERFACE = "org.apache.openjpa.persistence.OpenJPAEntityManager"; + String ECLIPSELINK_ENTITY_MANAGER_INTERFACE = "org.eclipse.persistence.jpa.JpaEntityManager"; + String HIBERNATE_ENTITY_MANAGER_INTERFACE = "org.hibernate.ejb.HibernateEntityManager"; + String HIBERNATE43_ENTITY_MANAGER_INTERFACE = "org.hibernate.jpa.HibernateEntityManager"; + + String HIBERNATE_JPA_METAMODEL_TYPE = "org.hibernate.ejb.metamodel.MetamodelImpl"; + String HIBERNATE43_JPA_METAMODEL_TYPE = "org.hibernate.jpa.internal.metamodel.MetamodelImpl"; + String ECLIPSELINK_JPA_METAMODEL_TYPE = "org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl"; + String OPENJPA_JPA_METAMODEL_TYPE = "org.apache.openjpa.persistence.meta.MetamodelImpl"; + } + + private final Iterable entityManagerClassNames; + private final Iterable metamodelClassNames; + + /** + * Creates a new {@link PersistenceProvider}. + * + * @param entityManagerClassNames the names of the provider specific {@link EntityManager} implementations. Must not + * be {@literal null} or empty. + */ + private PersistenceProvider(Iterable entityManagerClassNames, Iterable metamodelClassNames) { + + this.entityManagerClassNames = entityManagerClassNames; + this.metamodelClassNames = metamodelClassNames; + } + + /** + * Determines the {@link PersistenceProvider} from the given {@link EntityManager}. If no special one can be + * determined {@link #GENERIC_JPA} will be returned. + * + * @param em must not be {@literal null}. + * @return will never be {@literal null}. + */ + public static PersistenceProvider fromEntityManager(EntityManager em) { + + Assert.notNull(em); + + for (PersistenceProvider provider : values()) { + for (String entityManagerClassName : provider.entityManagerClassNames) { + if (isEntityManagerOfType(em, entityManagerClassName)) { + return provider; + } + } + } + + return GENERIC_JPA; + } + + public static PersistenceProvider fromMetamodel(Metamodel metamodel) { + + Assert.notNull(metamodel, "Metamodel must not be null!"); + + for (PersistenceProvider provider : values()) { + for (String metamodelClassName : provider.metamodelClassNames) { + if (isMetamodelOfType(metamodel, metamodelClassName)) { + return provider; + } + } + } + + return GENERIC_JPA; + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.jpa.repository.query.QueryExtractor#canExtractQuery + * () + */ + public boolean canExtractQuery() { + return true; + } + + /** + * Returns the placeholder to be used for simple count queries. Default implementation returns {@code *}. + * + * @return + */ + public String getCountQueryPlaceholder() { + return "x"; + } +} diff --git a/src/main/java/org/springframework/data/jpa/provider/ProxyIdAccessor.java b/src/main/java/org/springframework/data/jpa/provider/ProxyIdAccessor.java new file mode 100644 index 000000000..4a319662d --- /dev/null +++ b/src/main/java/org/springframework/data/jpa/provider/ProxyIdAccessor.java @@ -0,0 +1,41 @@ +/* + * Copyright 2014 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.provider; + +/** + * Interface for a persistence provider specific accessor of identifiers held in proxies. + * + * @author Oliver Gierke + */ +public interface ProxyIdAccessor { + + /** + * Returns whether the {@link ProxyIdAccessor} should be used for the given entity. Will inspect the entity to see + * whether it is a proxy so that lenient id lookup can be used. + * + * @param entity must not be {@literal null}. + * @return + */ + boolean shouldUseAccessorFor(Object entity); + + /** + * Returns the identifier of the given entity by leniently inspecting it for the identifier value. + * + * @param entity must not be {@literal null}. + * @return + */ + Object getIdentifierFrom(Object entity); +} diff --git a/src/main/java/org/springframework/data/jpa/repository/query/QueryExtractor.java b/src/main/java/org/springframework/data/jpa/provider/QueryExtractor.java similarity index 96% rename from src/main/java/org/springframework/data/jpa/repository/query/QueryExtractor.java rename to src/main/java/org/springframework/data/jpa/provider/QueryExtractor.java index fa3e930ad..244b5531a 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/QueryExtractor.java +++ b/src/main/java/org/springframework/data/jpa/provider/QueryExtractor.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.jpa.repository.query; +package org.springframework.data.jpa.provider; import javax.persistence.Query; diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategy.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategy.java index 0203c646b..7b1606394 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategy.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategy.java @@ -19,6 +19,7 @@ import java.lang.reflect.Method; import javax.persistence.EntityManager; +import org.springframework.data.jpa.provider.QueryExtractor; import org.springframework.data.repository.core.NamedQueries; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.query.EvaluationContextProvider; diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java index da219fe6b..084c5e30b 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java @@ -29,6 +29,7 @@ import javax.persistence.LockModeType; import javax.persistence.QueryHint; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.data.jpa.provider.QueryExtractor; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.Lock; import org.springframework.data.jpa.repository.Modifying; diff --git a/src/main/java/org/springframework/data/jpa/repository/query/NamedQuery.java b/src/main/java/org/springframework/data/jpa/repository/query/NamedQuery.java index 180c80c46..56b2eae80 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/NamedQuery.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/NamedQuery.java @@ -21,6 +21,7 @@ import javax.persistence.TypedQuery; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.data.jpa.provider.QueryExtractor; import org.springframework.data.repository.query.Parameters; import org.springframework.data.repository.query.QueryCreationException; import org.springframework.data.repository.query.RepositoryQuery; diff --git a/src/main/java/org/springframework/data/jpa/repository/support/JpaEntityInformationSupport.java b/src/main/java/org/springframework/data/jpa/repository/support/JpaEntityInformationSupport.java index d0cbe0e51..92d325f1f 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/JpaEntityInformationSupport.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/JpaEntityInformationSupport.java @@ -54,7 +54,7 @@ public abstract class JpaEntityInformationSupport ex * @return */ @SuppressWarnings({ "rawtypes", "unchecked" }) - public static JpaEntityInformation getMetadata(Class domainClass, EntityManager em) { + public static JpaEntityInformation getEntityInformation(Class domainClass, EntityManager em) { Assert.notNull(domainClass); Assert.notNull(em); diff --git a/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactory.java b/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactory.java index 24d609a3f..96cb0b531 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactory.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactory.java @@ -21,9 +21,10 @@ import java.io.Serializable; import javax.persistence.EntityManager; +import org.springframework.data.jpa.provider.PersistenceProvider; +import org.springframework.data.jpa.provider.QueryExtractor; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy; -import org.springframework.data.jpa.repository.query.QueryExtractor; import org.springframework.data.querydsl.QueryDslPredicateExecutor; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.core.support.RepositoryFactorySupport; @@ -142,6 +143,6 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport { @SuppressWarnings("unchecked") public JpaEntityInformation getEntityInformation(Class domainClass) { - return (JpaEntityInformation) JpaEntityInformationSupport.getMetadata(domainClass, entityManager); + return (JpaEntityInformation) JpaEntityInformationSupport.getEntityInformation(domainClass, entityManager); } } diff --git a/src/main/java/org/springframework/data/jpa/repository/support/PersistenceProvider.java b/src/main/java/org/springframework/data/jpa/repository/support/PersistenceProvider.java deleted file mode 100644 index f806ad02c..000000000 --- a/src/main/java/org/springframework/data/jpa/repository/support/PersistenceProvider.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2008-2014 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.springframework.data.jpa.repository.utils.JpaClassUtils.*; - -import java.util.Arrays; -import java.util.List; - -import javax.persistence.EntityManager; -import javax.persistence.Query; - -import org.apache.openjpa.persistence.OpenJPAQuery; -import org.eclipse.persistence.jpa.JpaQuery; -import org.hibernate.ejb.HibernateQuery; -import org.springframework.data.jpa.repository.query.QueryExtractor; -import org.springframework.util.Assert; - -/** - * Enumeration representing persistence providers to be used. - * - * @author Oliver Gierke - * @author Thomas Darimont - */ -public enum PersistenceProvider implements QueryExtractor { - - /** - * Hibernate persistence provider. - *

- * Since Hibernate 4.3 the location of the HibernateEntityManager moved to the org.hibernate.jpa package. In order to - * support both locations we interpret both classnames as a Hibernate {@code PersistenceProvider}. - * - * @see DATAJPA-444 - */ - HIBERNATE(Constants.HIBERNATE43_ENTITY_MANAGER_INTERFACE, Constants.HIBERNATE_ENTITY_MANAGER_INTERFACE) { - - public String extractQueryString(Query query) { - - return ((HibernateQuery) query).getHibernateQuery().getQueryString(); - } - - /** - * Return custom placeholder ({@code *}) as Hibernate does create invalid queries for count queries for objects with - * compound keys. - * - * @see HHH-4044 - * @see HHH-3096 - */ - @Override - protected String getCountQueryPlaceholder() { - - return "*"; - } - }, - - /** - * EclipseLink persistence provider. - */ - ECLIPSELINK(Constants.ECLIPSELINK_ENTITY_MANAGER_INTERFACE) { - - public String extractQueryString(Query query) { - - return ((JpaQuery) query).getDatabaseQuery().getJPQLString(); - } - - }, - - /** - * OpenJpa persistence provider. - */ - OPEN_JPA(Constants.OPENJPA_ENTITY_MANAGER_INTERFACE) { - - public String extractQueryString(Query query) { - - return ((OpenJPAQuery) query).getQueryString(); - } - }, - - /** - * Unknown special provider. Use standard JPA. - */ - GENERIC_JPA(Constants.GENERIC_JPA_ENTITY_MANAGER_INTERFACE) { - - public String extractQueryString(Query query) { - - return null; - } - - @Override - public boolean canExtractQuery() { - - return false; - } - }; - - /** - * Holds the PersistenceProvider specific interface names. - * - * @author Thomas Darimont - */ - static interface Constants { - - String GENERIC_JPA_ENTITY_MANAGER_INTERFACE = "javax.persistence.EntityManager"; - String OPENJPA_ENTITY_MANAGER_INTERFACE = "org.apache.openjpa.persistence.OpenJPAEntityManager"; - String ECLIPSELINK_ENTITY_MANAGER_INTERFACE = "org.eclipse.persistence.jpa.JpaEntityManager"; - String HIBERNATE_ENTITY_MANAGER_INTERFACE = "org.hibernate.ejb.HibernateEntityManager"; - String HIBERNATE43_ENTITY_MANAGER_INTERFACE = "org.hibernate.jpa.HibernateEntityManager"; - } - - private List entityManagerClassNames; - - /** - * Creates a new {@link PersistenceProvider}. - * - * @param entityManagerClassNames the names of the provider specific {@link EntityManager} implementations. Must not - * be {@literal null} or empty. - */ - private PersistenceProvider(String... entityManagerClassNames) { - - Assert.notEmpty(entityManagerClassNames, "EntityManagerClassNames must not be empty!"); - - this.entityManagerClassNames = Arrays.asList(entityManagerClassNames); - } - - /** - * Determines the {@link PersistenceProvider} from the given {@link EntityManager}. If no special one can be - * determined {@link #GENERIC_JPA} will be returned. - * - * @param em must not be {@literal null}. - * @return will never be {@literal null}. - */ - public static PersistenceProvider fromEntityManager(EntityManager em) { - - Assert.notNull(em); - - for (PersistenceProvider provider : values()) { - for (String entityManagerClassName : provider.entityManagerClassNames) { - - if (isEntityManagerOfType(em, entityManagerClassName)) { - return provider; - } - } - } - - return GENERIC_JPA; - } - - /* - * (non-Javadoc) - * - * @see - * org.springframework.data.jpa.repository.query.QueryExtractor#canExtractQuery - * () - */ - public boolean canExtractQuery() { - - return true; - } - - /** - * Returns the placeholder to be used for simple count queries. Default implementation returns {@code *}. - * - * @return - */ - protected String getCountQueryPlaceholder() { - - return "x"; - } -} diff --git a/src/main/java/org/springframework/data/jpa/repository/support/Querydsl.java b/src/main/java/org/springframework/data/jpa/repository/support/Querydsl.java index c46f153ef..9051a2cc6 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/Querydsl.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/Querydsl.java @@ -22,6 +22,7 @@ import javax.persistence.EntityManager; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Order; +import org.springframework.data.jpa.provider.PersistenceProvider; import org.springframework.data.mapping.PropertyPath; import org.springframework.data.querydsl.QSort; import org.springframework.util.Assert; diff --git a/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java b/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java index e90f4bcd4..e78daa36b 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java @@ -42,6 +42,7 @@ import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.provider.PersistenceProvider; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.query.Jpa21Utils; @@ -96,7 +97,7 @@ public class SimpleJpaRepository implements JpaRepos * @param em must not be {@literal null}. */ public SimpleJpaRepository(Class domainClass, EntityManager em) { - this(JpaEntityInformationSupport.getMetadata(domainClass, em), em); + this(JpaEntityInformationSupport.getEntityInformation(domainClass, em), em); } /** diff --git a/src/test/java/org/springframework/data/jpa/domain/sample/Category.java b/src/test/java/org/springframework/data/jpa/domain/sample/Category.java new file mode 100644 index 000000000..96230ebbe --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/domain/sample/Category.java @@ -0,0 +1,30 @@ +package org.springframework.data.jpa.domain.sample; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +public class Category { + + @Id @GeneratedValue private Long id; + + @ManyToOne(fetch = FetchType.LAZY)// + private Product product; + + public Category(Product product) { + this.product = product; + } + + protected Category() {} + + public Long getId() { + return id; + } + + public Product getProduct() { + return product; + } +} diff --git a/src/test/java/org/springframework/data/jpa/domain/sample/Product.java b/src/test/java/org/springframework/data/jpa/domain/sample/Product.java new file mode 100644 index 000000000..d63e78dfb --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/domain/sample/Product.java @@ -0,0 +1,15 @@ +package org.springframework.data.jpa.domain.sample; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Product { + + @Id @GeneratedValue private Long id; + + public Long getId() { + return id; + } +} diff --git a/src/test/java/org/springframework/data/jpa/mapping/JpaMetamodelMappingContextIntegrationTests.java b/src/test/java/org/springframework/data/jpa/mapping/JpaMetamodelMappingContextIntegrationTests.java index 14feb79b9..13f3c006c 100644 --- a/src/test/java/org/springframework/data/jpa/mapping/JpaMetamodelMappingContextIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/mapping/JpaMetamodelMappingContextIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 the original author or authors. + * Copyright 2012-2014 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. @@ -18,15 +18,32 @@ package org.springframework.data.jpa.mapping; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; +import java.util.Collections; +import javax.persistence.EntityManager; + +import org.hibernate.proxy.HibernateProxy; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.context.annotation.ImportResource; +import org.springframework.data.jpa.domain.sample.Category; +import org.springframework.data.jpa.domain.sample.Product; import org.springframework.data.jpa.domain.sample.User; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.jpa.repository.sample.CategoryRepository; +import org.springframework.data.jpa.repository.sample.ProductRepository; +import org.springframework.data.mapping.IdentifierAccessor; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallback; +import org.springframework.transaction.support.TransactionTemplate; /** * Integration tests for {@link JpaMetamodelMappingContext}. @@ -35,16 +52,28 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; * @since 1.3 */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration("classpath:infrastructure.xml") +@ContextConfiguration public class JpaMetamodelMappingContextIntegrationTests { + @Configuration + @ImportResource("classpath:infrastructure.xml") + @EnableJpaRepositories(basePackageClasses = CategoryRepository.class,// + includeFilters = @Filter(value = { CategoryRepository.class, ProductRepository.class }, + type = FilterType.ASSIGNABLE_TYPE)) + static class Config { + + } + JpaMetamodelMappingContext context; - @PersistenceContext EntityManager em; + @Autowired ProductRepository products; + @Autowired CategoryRepository categories; + @Autowired EntityManager em; + @Autowired PlatformTransactionManager transactionManager; @Before public void setUp() { - context = new JpaMetamodelMappingContext(em.getMetamodel()); + context = new JpaMetamodelMappingContext(Collections.singleton(em.getMetamodel())); } @Test @@ -95,4 +124,36 @@ public class JpaMetamodelMappingContextIntegrationTests { assertThat(entity.getPersistentProperty("colleagues").isEntity(), is(true)); } + + /** + * @see DATAJPA-630 + */ + @Test + public void lookingUpIdentifierOfProxyDoesNotInitializeProxy() { + + new TransactionTemplate(transactionManager).execute(new TransactionCallback() { + + @Override + public Void doInTransaction(TransactionStatus status) { + + Product product = products.save(new Product()); + Category category = categories.save(new Category(product)); + em.clear(); + + Category loaded = categories.findOne(category.getId()); + Product loadedProduct = loaded.getProduct(); + + JpaPersistentEntity entity = context.getPersistentEntity(Product.class); + IdentifierAccessor accessor = entity.getIdentifierAccessor(loadedProduct); + + assertThat(accessor.getIdentifier(), is((Object) product.getId())); + assertThat(loadedProduct, is(instanceOf(HibernateProxy.class))); + assertThat(((HibernateProxy) loadedProduct).getHibernateLazyInitializer().isUninitialized(), is(true)); + + status.setRollbackOnly(); + + 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 2c34a95f6..9b52d61f7 100644 --- a/src/test/java/org/springframework/data/jpa/mapping/JpaPersistentPropertyImplUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/mapping/JpaPersistentPropertyImplUnitTests.java @@ -18,6 +18,8 @@ package org.springframework.data.jpa.mapping; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; +import java.util.Collections; + import javax.persistence.Access; import javax.persistence.AccessType; import javax.persistence.Embeddable; @@ -50,7 +52,7 @@ public class JpaPersistentPropertyImplUnitTests { @Before public void setUp() { - context = new JpaMetamodelMappingContext(model); + context = new JpaMetamodelMappingContext(Collections.singleton(model)); entity = context.getPersistentEntity(Sample.class); } diff --git a/src/test/java/org/springframework/data/jpa/provider/PersistenceProviderIntegrationTests.java b/src/test/java/org/springframework/data/jpa/provider/PersistenceProviderIntegrationTests.java new file mode 100644 index 000000000..c72792c09 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/provider/PersistenceProviderIntegrationTests.java @@ -0,0 +1,98 @@ +/* + * Copyright 2014 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.provider; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import javax.persistence.EntityManager; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.context.annotation.ImportResource; +import org.springframework.data.jpa.domain.sample.Category; +import org.springframework.data.jpa.domain.sample.Product; +import org.springframework.data.jpa.provider.PersistenceProvider; +import org.springframework.data.jpa.provider.ProxyIdAccessor; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.jpa.repository.sample.CategoryRepository; +import org.springframework.data.jpa.repository.sample.ProductRepository; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallback; +import org.springframework.transaction.support.TransactionTemplate; + +/** + * Integration tests for {@link PersistenceProvider}. + * + * @author Oliver Gierke + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class PersistenceProviderIntegrationTests { + + @Configuration + @ImportResource("classpath:infrastructure.xml") + @EnableJpaRepositories(basePackageClasses = CategoryRepository.class,// + includeFilters = @Filter(value = { CategoryRepository.class, ProductRepository.class }, + type = FilterType.ASSIGNABLE_TYPE)) + static class Config { + + } + + @Autowired CategoryRepository categories; + @Autowired ProductRepository products; + @Autowired PlatformTransactionManager transactionManager; + @Autowired EntityManager em; + + Product product; + Category category; + + @Before + public void setUp() { + this.product = products.save(new Product()); + this.category = categories.save(new Category(product)); + } + + /** + * @see DATAJPA-630 + */ + @Test + public void testname() { + + new TransactionTemplate(transactionManager).execute(new TransactionCallback() { + + @Override + public Void doInTransaction(TransactionStatus status) { + + Product product = categories.findOne(category.getId()).getProduct(); + ProxyIdAccessor accessor = PersistenceProvider.fromEntityManager(em); + + assertThat(accessor.shouldUseAccessorFor(product), is(true)); + assertThat(accessor.getIdentifierFrom(product).toString(), is((Object) product.getId().toString())); + + return null; + } + }); + } +} diff --git a/src/test/java/org/springframework/data/jpa/repository/support/PersistenceProviderTests.java b/src/test/java/org/springframework/data/jpa/provider/PersistenceProviderUnitTests.java similarity index 82% rename from src/test/java/org/springframework/data/jpa/repository/support/PersistenceProviderTests.java rename to src/test/java/org/springframework/data/jpa/provider/PersistenceProviderUnitTests.java index 594eb2c88..41f809bd6 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/PersistenceProviderTests.java +++ b/src/test/java/org/springframework/data/jpa/provider/PersistenceProviderUnitTests.java @@ -13,10 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.jpa.repository.support; +package org.springframework.data.jpa.provider; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; +import static org.springframework.data.jpa.provider.PersistenceProvider.*; +import static org.springframework.data.jpa.provider.PersistenceProvider.Constants.*; import java.util.ArrayList; import java.util.List; @@ -28,6 +30,7 @@ import org.junit.Test; import org.mockito.Mockito; import org.springframework.asm.ClassWriter; import org.springframework.asm.Opcodes; +import org.springframework.data.jpa.provider.PersistenceProvider; import org.springframework.instrument.classloading.ShadowingClassLoader; import org.springframework.util.ClassUtils; @@ -35,27 +38,28 @@ import org.springframework.util.ClassUtils; * Tests for PersistenceProvider detection logic in {@link PersistenceProvider}. * * @author Thomas Darimont + * @author Oliver Gierke */ -public class PersistenceProviderTests { +public class PersistenceProviderUnitTests { - private ShadowingClassLoader shadowingClassLoader; + ShadowingClassLoader shadowingClassLoader; @Before public void setup() { - shadowingClassLoader = new ShadowingClassLoader(getClass().getClassLoader()); + this.shadowingClassLoader = new ShadowingClassLoader(getClass().getClassLoader()); } /** * @see DATAJPA-444 */ @Test - public void detectsHibernatePersistenceProviderForHibernateVersionLessThan4dot3() throws Exception { + public void detectsHibernatePersistenceProviderForHibernateVersionLessThan4Dot3() throws Exception { shadowingClassLoader.excludePackage("org.hibernate"); - EntityManager em = mockProviderSpecificEntityManagerInterface(PersistenceProvider.Constants.HIBERNATE_ENTITY_MANAGER_INTERFACE); + EntityManager em = mockProviderSpecificEntityManagerInterface(HIBERNATE_ENTITY_MANAGER_INTERFACE); - assertThat(PersistenceProvider.fromEntityManager(em), is(PersistenceProvider.HIBERNATE)); + assertThat(fromEntityManager(em), is(HIBERNATE)); } /** @@ -66,9 +70,9 @@ public class PersistenceProviderTests { shadowingClassLoader.excludePackage("org.hibernate"); - EntityManager em = mockProviderSpecificEntityManagerInterface(PersistenceProvider.Constants.HIBERNATE43_ENTITY_MANAGER_INTERFACE); + EntityManager em = mockProviderSpecificEntityManagerInterface(HIBERNATE43_ENTITY_MANAGER_INTERFACE); - assertThat(PersistenceProvider.fromEntityManager(em), is(PersistenceProvider.HIBERNATE)); + assertThat(fromEntityManager(em), is(HIBERNATE)); } @Test @@ -76,9 +80,9 @@ public class PersistenceProviderTests { shadowingClassLoader.excludePackage("org.apache.openjpa.persistence"); - EntityManager em = mockProviderSpecificEntityManagerInterface(PersistenceProvider.Constants.OPENJPA_ENTITY_MANAGER_INTERFACE); + EntityManager em = mockProviderSpecificEntityManagerInterface(OPENJPA_ENTITY_MANAGER_INTERFACE); - assertThat(PersistenceProvider.fromEntityManager(em), is(PersistenceProvider.OPEN_JPA)); + assertThat(fromEntityManager(em), is(OPEN_JPA)); } @Test @@ -86,9 +90,9 @@ public class PersistenceProviderTests { shadowingClassLoader.excludePackage("org.eclipse.persistence.jpa"); - EntityManager em = mockProviderSpecificEntityManagerInterface(PersistenceProvider.Constants.ECLIPSELINK_ENTITY_MANAGER_INTERFACE); + EntityManager em = mockProviderSpecificEntityManagerInterface(ECLIPSELINK_ENTITY_MANAGER_INTERFACE); - assertThat(PersistenceProvider.fromEntityManager(em), is(PersistenceProvider.ECLIPSELINK)); + assertThat(fromEntityManager(em), is(ECLIPSELINK)); } @Test @@ -96,7 +100,7 @@ public class PersistenceProviderTests { EntityManager em = mockProviderSpecificEntityManagerInterface("foo.bar.unknown.jpa.JpaEntityManager"); - assertThat(PersistenceProvider.fromEntityManager(em), is(PersistenceProvider.GENERIC_JPA)); + assertThat(fromEntityManager(em), is(GENERIC_JPA)); } private EntityManager mockProviderSpecificEntityManagerInterface(String interfaceName) throws ClassNotFoundException { diff --git a/src/test/java/org/springframework/data/jpa/repository/CrudMethodMetadataIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/CrudMethodMetadataUnitTests.java similarity index 97% rename from src/test/java/org/springframework/data/jpa/repository/CrudMethodMetadataIntegrationTests.java rename to src/test/java/org/springframework/data/jpa/repository/CrudMethodMetadataUnitTests.java index 8fe76aa15..3f3a20553 100644 --- a/src/test/java/org/springframework/data/jpa/repository/CrudMethodMetadataIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/CrudMethodMetadataUnitTests.java @@ -48,7 +48,7 @@ import org.springframework.data.jpa.repository.support.JpaRepositoryFactory; * @author Thomas Darimont */ @RunWith(MockitoJUnitRunner.class) -public class CrudMethodMetadataIntegrationTests { +public class CrudMethodMetadataUnitTests { @Mock EntityManager em; @Mock EntityManagerFactory emf; @@ -65,6 +65,7 @@ public class CrudMethodMetadataIntegrationTests { when(information.getJavaType()).thenReturn(Role.class); + when(em.getDelegate()).thenReturn(em); when(em.getEntityManagerFactory()).thenReturn(emf); when(emf.createEntityManager()).thenReturn(em); diff --git a/src/test/java/org/springframework/data/jpa/repository/JavaConfigUserRepositoryTests.java b/src/test/java/org/springframework/data/jpa/repository/JavaConfigUserRepositoryTests.java index c4ca76702..5f4ad62f1 100644 --- a/src/test/java/org/springframework/data/jpa/repository/JavaConfigUserRepositoryTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/JavaConfigUserRepositoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2014 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. @@ -22,7 +22,6 @@ import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.junit.Test; -import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.PropertiesFactoryBean; diff --git a/src/test/java/org/springframework/data/jpa/repository/query/AbstractJpaQueryTests.java b/src/test/java/org/springframework/data/jpa/repository/query/AbstractJpaQueryTests.java index 24d07fd51..5fd9fe17f 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/AbstractJpaQueryTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/AbstractJpaQueryTests.java @@ -34,11 +34,12 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.data.jpa.domain.sample.User; +import org.springframework.data.jpa.provider.PersistenceProvider; +import org.springframework.data.jpa.provider.QueryExtractor; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.EntityGraph.EntityGraphType; import org.springframework.data.jpa.repository.Lock; import org.springframework.data.jpa.repository.QueryHints; -import org.springframework.data.jpa.repository.support.PersistenceProvider; import org.springframework.data.repository.Repository; import org.springframework.data.repository.core.support.DefaultRepositoryMetadata; import org.springframework.test.context.ContextConfiguration; diff --git a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java index f3c11bbda..aed61b6d9 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryLookupStrategyUnitTests.java @@ -35,6 +35,7 @@ import org.mockito.runners.MockitoJUnitRunner; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.sample.User; +import org.springframework.data.jpa.provider.QueryExtractor; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.Repository; import org.springframework.data.repository.core.NamedQueries; diff --git a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryMethodUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryMethodUnitTests.java index 6e0db24d6..f948142c2 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryMethodUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryMethodUnitTests.java @@ -36,6 +36,7 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.sample.User; +import org.springframework.data.jpa.provider.QueryExtractor; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.EntityGraph.EntityGraphType; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/src/test/java/org/springframework/data/jpa/repository/query/NamedQueryUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/NamedQueryUnitTests.java index 3b6b7a1db..7bb346028 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/NamedQueryUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/NamedQueryUnitTests.java @@ -30,6 +30,7 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.provider.QueryExtractor; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.query.QueryCreationException; diff --git a/src/test/java/org/springframework/data/jpa/repository/query/PartTreeJpaQueryIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/query/PartTreeJpaQueryIntegrationTests.java index a6f16b997..bf6f25f7a 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/PartTreeJpaQueryIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/PartTreeJpaQueryIntegrationTests.java @@ -42,8 +42,8 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.sample.User; +import org.springframework.data.jpa.provider.PersistenceProvider; import org.springframework.data.jpa.repository.Temporal; -import org.springframework.data.jpa.repository.support.PersistenceProvider; import org.springframework.data.repository.Repository; import org.springframework.data.repository.core.support.DefaultRepositoryMetadata; import org.springframework.data.repository.query.Param; diff --git a/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java index d2d0fbfb8..1d611115c 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java @@ -40,6 +40,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.sample.User; +import org.springframework.data.jpa.provider.QueryExtractor; import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.sample.UserRepository; import org.springframework.data.repository.core.RepositoryMetadata; diff --git a/src/test/java/org/springframework/data/jpa/repository/sample/CategoryRepository.java b/src/test/java/org/springframework/data/jpa/repository/sample/CategoryRepository.java new file mode 100644 index 000000000..a0844d396 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/sample/CategoryRepository.java @@ -0,0 +1,24 @@ +/* + * Copyright 2014 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.sample; + +import org.springframework.data.jpa.domain.sample.Category; +import org.springframework.data.repository.CrudRepository; + +/** + * @author Oliver Gierke + */ +public interface CategoryRepository extends CrudRepository {} diff --git a/src/test/java/org/springframework/data/jpa/repository/sample/ProductRepository.java b/src/test/java/org/springframework/data/jpa/repository/sample/ProductRepository.java new file mode 100644 index 000000000..7ff2c7a6c --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/sample/ProductRepository.java @@ -0,0 +1,26 @@ +/* + * Copyright 2014 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.sample; + +import org.springframework.data.jpa.domain.sample.Product; +import org.springframework.data.jpa.repository.JpaRepository; + +/** + * @author Oliver Gierke + */ +public interface ProductRepository extends JpaRepository { + +} 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 index 85efa364a..3590c8600 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/EclipseLinkJpaMetamodelEntityInformationIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/support/EclipseLinkJpaMetamodelEntityInformationIntegrationTests.java @@ -38,7 +38,8 @@ public class EclipseLinkJpaMetamodelEntityInformationIntegrationTests extends */ @Test public void reactivatedDetectsIdTypeForMappedSuperclass() { - JpaEntityInformation information = JpaEntityInformationSupport.getMetadata(AbstractPersistable.class, em); + JpaEntityInformation information = JpaEntityInformationSupport.getEntityInformation( + AbstractPersistable.class, em); assertEquals(String.class, information.getIdType()); } @@ -56,10 +57,6 @@ public class EclipseLinkJpaMetamodelEntityInformationIntegrationTests extends @Ignore public void detectsNewStateForEntityWithPrimitiveId() {} - /* - * (non-Javadoc) - * @see org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformationIntegrationTests#considersEntityWithUnSetCompundIdNew() - */ @Override @Ignore public void considersEntityWithUnsetCompundIdNew() {} diff --git a/src/test/java/org/springframework/data/jpa/repository/support/EclipseLinkProxyIdAccessorTests.java b/src/test/java/org/springframework/data/jpa/repository/support/EclipseLinkProxyIdAccessorTests.java new file mode 100644 index 000000000..f9146c00e --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/support/EclipseLinkProxyIdAccessorTests.java @@ -0,0 +1,40 @@ +/* + * Copyright 2014 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.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.data.jpa.provider.PersistenceProviderIntegrationTests; +import org.springframework.test.context.ContextConfiguration; + +/** + * @author Oliver Gierke + */ +@ContextConfiguration(classes = EclipseLinkProxyIdAccessorTests.EclipseLinkConfig.class) +public class EclipseLinkProxyIdAccessorTests extends PersistenceProviderIntegrationTests { + + @Configuration + @ImportResource("classpath:eclipselink.xml") + static class EclipseLinkConfig {} + + /** + * Do not execute the test as EclipseLink does not create a lazy-loading proxy as expected. + */ + @Override + @Ignore + public void testname() {} +} diff --git a/src/test/java/org/springframework/data/jpa/repository/support/JpaEntityInformationSupportUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/support/JpaEntityInformationSupportUnitTests.java index c16866a92..6ff5b9ae0 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/JpaEntityInformationSupportUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/support/JpaEntityInformationSupportUnitTests.java @@ -61,7 +61,7 @@ public class JpaEntityInformationSupportUnitTests { public void rejectsClassNotBeingFoundInMetamodel() { when(em.getMetamodel()).thenReturn(metaModel); - JpaEntityInformationSupport.getMetadata(User.class, em); + JpaEntityInformationSupport.getEntityInformation(User.class, em); } static class User { 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 d3340749f..0c39a5ef8 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 @@ -17,6 +17,7 @@ package org.springframework.data.jpa.repository.support; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; +import static org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.*; import java.io.Serializable; import java.sql.Timestamp; @@ -43,7 +44,6 @@ import org.springframework.data.jpa.domain.sample.PersistableWithIdClassPK; import org.springframework.data.jpa.domain.sample.PrimitiveVersionProperty; import org.springframework.data.jpa.domain.sample.Role; import org.springframework.data.jpa.domain.sample.SampleWithIdClass; -import org.springframework.data.jpa.domain.sample.SampleWithIdClass.SampleWithIdClassPK; import org.springframework.data.jpa.domain.sample.SampleWithPrimitiveId; import org.springframework.data.jpa.domain.sample.SampleWithTimestampVersion; import org.springframework.data.jpa.domain.sample.User; @@ -68,7 +68,7 @@ public class JpaMetamodelEntityInformationIntegrationTests { @Test public void detectsIdTypeForEntity() { - JpaEntityInformation information = JpaEntityInformationSupport.getMetadata(User.class, em); + JpaEntityInformation information = getEntityInformation(User.class, em); assertThat(information.getIdType(), is(typeCompatibleWith(Integer.class))); } @@ -83,7 +83,7 @@ public class JpaMetamodelEntityInformationIntegrationTests { @Ignore public void detectsIdTypeForMappedSuperclass() { - JpaEntityInformation information = JpaEntityInformationSupport.getMetadata(AbstractPersistable.class, em); + JpaEntityInformation information = getEntityInformation(AbstractPersistable.class, em); assertEquals(Serializable.class, information.getIdType()); } @@ -93,8 +93,7 @@ public class JpaMetamodelEntityInformationIntegrationTests { @Test public void detectsIdClass() { - EntityInformation information = JpaEntityInformationSupport.getMetadata( - PersistableWithIdClass.class, em); + EntityInformation information = getEntityInformation(PersistableWithIdClass.class, em); assertThat(information.getIdType(), is(typeCompatibleWith(PersistableWithIdClassPK.class))); } @@ -106,8 +105,7 @@ public class JpaMetamodelEntityInformationIntegrationTests { PersistableWithIdClass entity = new PersistableWithIdClass(2L, 4L); - JpaEntityInformation information = JpaEntityInformationSupport.getMetadata( - PersistableWithIdClass.class, em); + JpaEntityInformation information = getEntityInformation(PersistableWithIdClass.class, em); Object id = information.getId(entity); assertThat(id, is(instanceOf(PersistableWithIdClassPK.class))); @@ -227,8 +225,7 @@ public class JpaMetamodelEntityInformationIntegrationTests { @Test public void considersEntityWithUnsetCompundIdNew() { - EntityInformation information = new JpaMetamodelEntityInformation( - SampleWithIdClass.class, em.getMetamodel()); + EntityInformation information = getEntityInformation(SampleWithIdClass.class, em); assertThat(information.isNew(new SampleWithIdClass()), is(true)); } @@ -239,7 +236,8 @@ public class JpaMetamodelEntityInformationIntegrationTests { @Test public void considersEntityWithSetTimestampVersionNotNew() { - EntityInformation information = getEntityInformation(SampleWithTimestampVersion.class); + EntityInformation information = getEntityInformation( + SampleWithTimestampVersion.class, em); SampleWithTimestampVersion entity = new SampleWithTimestampVersion(); entity.version = new Timestamp(new Date().getTime()); @@ -253,7 +251,7 @@ public class JpaMetamodelEntityInformationIntegrationTests { @Test public void considersEntityWithNonPrimitiveNonNullIdTypeNotNew() { - EntityInformation information = getEntityInformation(User.class); + EntityInformation information = getEntityInformation(User.class, em); User user = new User(); assertThat(information.isNew(user), is(true)); @@ -262,10 +260,6 @@ public class JpaMetamodelEntityInformationIntegrationTests { assertThat(information.isNew(user), is(false)); } - private EntityInformation getEntityInformation(Class domainType) { - return new JpaMetamodelEntityInformation(domainType, em.getMetamodel()); - } - protected String getMetadadataPersitenceUnitName() { return "metadata"; } diff --git a/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryUnitTests.java index e70767c99..c470443d7 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryUnitTests.java @@ -52,27 +52,27 @@ public class JpaRepositoryFactoryUnitTests { JpaRepositoryFactory factory; @Mock EntityManager entityManager; - @Mock @SuppressWarnings("rawtypes") JpaEntityInformation metadata; + @Mock @SuppressWarnings("rawtypes") JpaEntityInformation entityInformation; @Mock EntityManagerFactory emf; @Before public void setUp() { + when(entityManager.getEntityManagerFactory()).thenReturn(emf); + when(entityManager.getDelegate()).thenReturn(entityManager); + when(emf.createEntityManager()).thenReturn(entityManager); + // Setup standard factory configuration factory = new JpaRepositoryFactory(entityManager) { @Override @SuppressWarnings("unchecked") public JpaEntityInformation getEntityInformation(Class domainClass) { - - return metadata; + return entityInformation; }; }; factory.setQueryLookupStrategyKey(Key.CREATE_IF_NOT_FOUND); - - when(entityManager.getEntityManagerFactory()).thenReturn(emf); - when(emf.createEntityManager()).thenReturn(entityManager); } /** @@ -140,7 +140,7 @@ public class JpaRepositoryFactoryUnitTests { @Test public void usesQueryDslRepositoryIfInterfaceImplementsExecutor() { - when(metadata.getJavaType()).thenReturn(User.class); + when(entityInformation.getJavaType()).thenReturn(User.class); assertEquals(QueryDslJpaRepository.class, factory.getRepositoryBaseClass(new DefaultRepositoryMetadata(QueryDslSampleRepository.class))); diff --git a/src/test/java/org/springframework/data/jpa/repository/support/OpenJpaProxyIdAccessorTests.java b/src/test/java/org/springframework/data/jpa/repository/support/OpenJpaProxyIdAccessorTests.java new file mode 100644 index 000000000..3b4723f16 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/support/OpenJpaProxyIdAccessorTests.java @@ -0,0 +1,32 @@ +/* + * Copyright 2014 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.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.data.jpa.provider.PersistenceProviderIntegrationTests; +import org.springframework.test.context.ContextConfiguration; + +/** + * @author Oliver Gierke + */ +@ContextConfiguration +public class OpenJpaProxyIdAccessorTests extends PersistenceProviderIntegrationTests { + + @Configuration + @ImportResource("classpath:openjpa.xml") + static class Config {} +} diff --git a/src/test/java/org/springframework/data/jpa/repository/support/SimpleJpaRepositoryUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/support/SimpleJpaRepositoryUnitTests.java index 2e6e505d7..ecf07b181 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/SimpleJpaRepositoryUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/support/SimpleJpaRepositoryUnitTests.java @@ -53,6 +53,8 @@ public class SimpleJpaRepositoryUnitTests { @Before public void setUp() { + when(em.getDelegate()).thenReturn(em); + when(information.getJavaType()).thenReturn(User.class); when(em.getCriteriaBuilder()).thenReturn(builder); diff --git a/src/test/resources/META-INF/persistence.xml b/src/test/resources/META-INF/persistence.xml index e58401db3..212f4120a 100644 --- a/src/test/resources/META-INF/persistence.xml +++ b/src/test/resources/META-INF/persistence.xml @@ -10,6 +10,7 @@ org.springframework.data.jpa.domain.sample.AnnotatedAuditableUser org.springframework.data.jpa.domain.sample.AuditableRole org.springframework.data.jpa.domain.sample.AuditableUser + org.springframework.data.jpa.domain.sample.Category org.springframework.data.jpa.domain.sample.Child org.springframework.data.jpa.domain.sample.ConcreteType1 org.springframework.data.jpa.domain.sample.ConcreteType2 @@ -26,6 +27,7 @@ org.springframework.data.jpa.domain.sample.Parent org.springframework.data.jpa.domain.sample.PersistableWithIdClass org.springframework.data.jpa.domain.sample.PrimitiveVersionProperty + org.springframework.data.jpa.domain.sample.Product org.springframework.data.jpa.domain.sample.Role org.springframework.data.jpa.domain.sample.SampleEntity org.springframework.data.jpa.domain.sample.SampleEntityPK diff --git a/src/test/resources/META-INF/persistence2.xml b/src/test/resources/META-INF/persistence2.xml index 50cd7584f..4ecbc5e16 100644 --- a/src/test/resources/META-INF/persistence2.xml +++ b/src/test/resources/META-INF/persistence2.xml @@ -6,24 +6,28 @@ org.springframework.data.jpa.domain.sample.AnnotatedAuditableUser org.springframework.data.jpa.domain.sample.AuditableRole org.springframework.data.jpa.domain.sample.AuditableUser - org.springframework.data.jpa.domain.sample.User - org.springframework.data.jpa.domain.sample.SpecialUser - org.springframework.data.jpa.domain.sample.Role + org.springframework.data.jpa.domain.sample.Category org.springframework.data.jpa.domain.sample.MailMessage org.springframework.data.jpa.domain.sample.MailSender org.springframework.data.jpa.domain.sample.MailUser + org.springframework.data.jpa.domain.sample.Product + org.springframework.data.jpa.domain.sample.Role + org.springframework.data.jpa.domain.sample.SpecialUser + org.springframework.data.jpa.domain.sample.User true - org.springframework.data.jpa.domain.sample.User - org.springframework.data.jpa.domain.sample.SpecialUser - org.springframework.data.jpa.domain.sample.Role org.springframework.data.jpa.domain.sample.AnnotatedAuditableUser org.springframework.data.jpa.domain.sample.AuditableUser org.springframework.data.jpa.domain.sample.AuditableRole + org.springframework.data.jpa.domain.sample.Category org.springframework.data.jpa.domain.sample.MailMessage org.springframework.data.jpa.domain.sample.MailSender org.springframework.data.jpa.domain.sample.MailUser + org.springframework.data.jpa.domain.sample.Product + org.springframework.data.jpa.domain.sample.Role + org.springframework.data.jpa.domain.sample.SpecialUser + org.springframework.data.jpa.domain.sample.User true diff --git a/template.mf b/template.mf index 42028fd79..95ee501d7 100644 --- a/template.mf +++ b/template.mf @@ -12,7 +12,7 @@ Import-Template: javax.annotation.*;version="0.0.0", javax.enterprise.*;version="${cdi:[=.=.=,+1.0.0)}";resolution:=optional, org.aopalliance.*;version="[1.0.0,2.0.0)", - org.apache.openjpa.persistence.*;version="${openjpa:[=.=.=,+1.0.0)}";resolution:=optional, + org.apache.openjpa.*;version="${openjpa:[=.=.=,+1.0.0)}";resolution:=optional, org.aspectj.*;version="${aspectj:[=.=.=,+1.0.0)}";resolution:=optional, org.eclipse.persistence.*;version="${eclipselink:[=.=.=,+1.0.0)}";resolution:=optional, org.hibernate.*;version="[3.6.10,4.4.0)";resolution:=optional,