diff --git a/src/main/java/org/springframework/data/jpa/mapping/JpaPersistentPropertyImpl.java b/src/main/java/org/springframework/data/jpa/mapping/JpaPersistentPropertyImpl.java index 51000b98a..4f7bf2f10 100644 --- a/src/main/java/org/springframework/data/jpa/mapping/JpaPersistentPropertyImpl.java +++ b/src/main/java/org/springframework/data/jpa/mapping/JpaPersistentPropertyImpl.java @@ -35,7 +35,9 @@ import javax.persistence.OneToOne; import javax.persistence.OrderColumn; import javax.persistence.Transient; import javax.persistence.Version; +import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.Metamodel; +import javax.persistence.metamodel.SingularAttribute; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.data.annotation.AccessType.Type; @@ -54,6 +56,7 @@ import org.springframework.util.Assert; * {@link JpaPersistentProperty} implementation usind a JPA {@link Metamodel}. * * @author Oliver Gierke + * @author Thomas Darimont * @author Greg Turnquist * @author Christoph Strobl * @author Mark Paluch @@ -94,6 +97,7 @@ class JpaPersistentPropertyImpl extends AnnotationBasedPersistentProperty associationTargetType; private final boolean updateable; private final JpaMetamodel metamodel; + private final EntityType entityType; /** * Creates a new {@link JpaPersistentPropertyImpl} @@ -110,12 +114,35 @@ class JpaPersistentPropertyImpl extends AnnotationBasedPersistentProperty tryResolveEntityType(Metamodel metamodel, Class type) { + + EntityType ownerEntityType = null; + + for (EntityType entityType : metamodel.getEntities()) { + if (entityType.getJavaType().equals(type)) { + ownerEntityType = entityType; + break; + } + } + + return ownerEntityType; + } + /* * (non-Javadoc) * @see org.springframework.data.mapping.model.AbstractPersistentProperty#getActualType() @@ -141,7 +168,27 @@ class JpaPersistentPropertyImpl extends AnnotationBasedPersistentProperty isAnnotationPresent(it)); + + boolean isId ID_ANNOTATIONS.stream().anyMatch(it -> isAnnotationPresent(it)); + + if (isId) { + return true; + } + + if (isIdPropertyCandidateAccordingToMetaModel()) { + + SingularAttribute idAttribute = entityType.getId(getType()); + if (idAttribute.getName().equals(getName())) { + return true; + } + } + + return false; + } + + private boolean isIdPropertyCandidateAccordingToMetaModel() { + return entityType != null && entityType.hasSingleIdAttribute() + && entityType.getIdType().getJavaType().equals(getType()); } /* diff --git a/src/test/java/org/springframework/data/jpa/domain/sample/OrmXmlEntity.java b/src/test/java/org/springframework/data/jpa/domain/sample/OrmXmlEntity.java new file mode 100644 index 000000000..33ca3a449 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/domain/sample/OrmXmlEntity.java @@ -0,0 +1,45 @@ +/* + * Copyright 2015 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.domain.sample; + +/** + * This entity serves as a test object for orm.xml configuration and MUST NOT be configured via annotations! + * + * @author Thomas Darimont + */ +public class OrmXmlEntity { + + private Long id; + + private String property1; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getProperty1() { + return property1; + } + + public void setProperty1(String property1) { + this.property1 = property1; + } + +} 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 d8512a98e..93731aac4 100644 --- a/src/test/java/org/springframework/data/jpa/mapping/JpaMetamodelMappingContextIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/mapping/JpaMetamodelMappingContextIntegrationTests.java @@ -32,6 +32,7 @@ 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.OrmXmlEntity; import org.springframework.data.jpa.domain.sample.Product; import org.springframework.data.jpa.domain.sample.User; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @@ -47,6 +48,7 @@ import org.springframework.transaction.support.TransactionTemplate; * Integration tests for {@link JpaMetamodelMappingContext}. * * @author Oliver Gierke + * @author Thomas Darimont * @since 1.3 */ @RunWith(SpringJUnit4ClassRunner.class) @@ -147,4 +149,15 @@ public class JpaMetamodelMappingContextIntegrationTests { return null; }); } + + /** + * @see DATAJPA-658 + */ + @Test + public void shouldDetectIdPropertyForEntityConfiguredViaOrmXmlWithoutAnyAnnotations() { + + JpaPersistentEntity entity = context.getPersistentEntity(OrmXmlEntity.class); + + assertThat(entity.getIdProperty(), is(notNullValue())); + } } diff --git a/src/test/resources/META-INF/orm.xml b/src/test/resources/META-INF/orm.xml index 89cbea582..e8bee2914 100644 --- a/src/test/resources/META-INF/orm.xml +++ b/src/test/resources/META-INF/orm.xml @@ -1,19 +1,24 @@ - + - - - - - - - + + + + + + + SELECT u FROM User u WHERE u.lastname = ?1 - - + + @@ -21,5 +26,14 @@ - + + + + + + + + + +