From 6824cc158ee5f0c519f3b33ace64f8154fb805f1 Mon Sep 17 00:00:00 2001 From: Thomas Darimont Date: Thu, 25 Jul 2013 14:09:22 +0200 Subject: [PATCH] DATAJPA-269 - Add support for derived identifier of nested composite keys. Extended JpaMetamodelEntityInformation to deal with entities with custom composite keys for which we have to derive the identifier. Introduced IdentifierDerivingDirectFieldAccessFallbackBeanWrapper that is capable of deriving identifier values. Added test case to verify the support for save / load of entities with custom composite keys. Original pull request: #28. --- .../JpaMetamodelEntityInformation.java | 69 ++++++++++- .../sample/EmbeddedIdExampleDepartment.java | 76 ++++++++++++ .../sample/EmbeddedIdExampleEmployee.java | 46 ++++++++ .../sample/EmbeddedIdExampleEmployeePK.java | 77 ++++++++++++ .../sample/IdClassExampleDepartment.java | 77 ++++++++++++ .../domain/sample/IdClassExampleEmployee.java | 45 +++++++ .../sample/IdClassExampleEmployeePK.java | 79 +++++++++++++ ...Jpa269RepositoryWithCompositeKeyTests.java | 111 ++++++++++++++++++ .../EmployeeRepositoryWithEmbeddedId.java | 28 +++++ .../sample/EmployeeRepositoryWithIdClass.java | 27 +++++ src/test/resources/META-INF/persistence.xml | 5 + 11 files changed, 639 insertions(+), 1 deletion(-) create mode 100644 src/test/java/org/springframework/data/jpa/domain/sample/EmbeddedIdExampleDepartment.java create mode 100644 src/test/java/org/springframework/data/jpa/domain/sample/EmbeddedIdExampleEmployee.java create mode 100644 src/test/java/org/springframework/data/jpa/domain/sample/EmbeddedIdExampleEmployeePK.java create mode 100644 src/test/java/org/springframework/data/jpa/domain/sample/IdClassExampleDepartment.java create mode 100644 src/test/java/org/springframework/data/jpa/domain/sample/IdClassExampleEmployee.java create mode 100644 src/test/java/org/springframework/data/jpa/domain/sample/IdClassExampleEmployeePK.java create mode 100644 src/test/java/org/springframework/data/jpa/repository/DataJpa269RepositoryWithCompositeKeyTests.java create mode 100644 src/test/java/org/springframework/data/jpa/repository/sample/EmployeeRepositoryWithEmbeddedId.java create mode 100644 src/test/java/org/springframework/data/jpa/repository/sample/EmployeeRepositoryWithIdClass.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 8fe4a779e..febc902c4 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 @@ -28,6 +28,7 @@ import javax.persistence.metamodel.IdentifiableType; import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.Metamodel; import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.Type.PersistenceType; import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; @@ -48,6 +49,7 @@ public class JpaMetamodelEntityInformation extends J private final IdMetadata idMetadata; private final SingularAttribute versionAttribute; + private final Metamodel metamodel; /** * Creates a new {@link JpaMetamodelEntityInformation} for the given domain class and {@link Metamodel}. @@ -60,6 +62,8 @@ public class JpaMetamodelEntityInformation extends J super(domainClass); Assert.notNull(metamodel); + this.metamodel = metamodel; + ManagedType type = metamodel.managedType(domainClass); if (type == null) { @@ -106,7 +110,7 @@ public class JpaMetamodelEntityInformation extends J return (ID) entityWrapper.getPropertyValue(idMetadata.getSimpleIdAttribute().getName()); } - BeanWrapper idWrapper = new DirectFieldAccessFallbackBeanWrapper(idMetadata.getType()); + BeanWrapper idWrapper = new IdentifierDerivingDirectFieldAccessFallbackBeanWrapper(idMetadata.getType(), metamodel); boolean partialIdValueFound = false; for (SingularAttribute attribute : idMetadata) { @@ -291,4 +295,67 @@ public class JpaMetamodelEntityInformation extends J } } } + + /** + * Custom extension of {@link DirectFieldAccessFallbackBeanWrapper} that allows to derived the identifier if composite + * keys with complex key attribute types (e.g. types that are annotated with {@code @Entity} themselves) are used. + * + * @author Thomas Darimont + */ + private static class IdentifierDerivingDirectFieldAccessFallbackBeanWrapper extends + DirectFieldAccessFallbackBeanWrapper { + + private final Metamodel metamodel; + + public IdentifierDerivingDirectFieldAccessFallbackBeanWrapper(Class type, Metamodel metamodel) { + super(type); + this.metamodel = metamodel; + } + + /** + * In addition to the functionality described in {@link BeanWrapperImpl} it is checked whether we have a nested + * entity that is part of the id key. If this is the case, we need to derive the identifier of the nested entity. + * + * @see org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.DirectFieldAccessFallbackBeanWrapper#setPropertyValue(java.lang.String, + * java.lang.Object) + */ + @Override + public void setPropertyValue(String propertyName, Object value) { + + if (isIdentifierDerivationNecessary(value)) { + + // Derive the identifer from the nested entity that is part of the composite key. + @SuppressWarnings({ "rawtypes", "unchecked" }) + JpaMetamodelEntityInformation nestedEntityInformation = new JpaMetamodelEntityInformation(value.getClass(), + this.metamodel); + Object nestedIdPropertyValue = new DirectFieldAccessFallbackBeanWrapper(value) + .getPropertyValue(nestedEntityInformation.getIdAttribute().getName()); + super.setPropertyValue(propertyName, nestedIdPropertyValue); + + return; + } + + super.setPropertyValue(propertyName, value); + } + + /** + * @param value + * @return {@literal true} if the given value is not {@literal null} and a mapped persistable entity otherwise + * {@literal false} + */ + private boolean isIdentifierDerivationNecessary(Object value) { + + if (value == null) { + return false; + } + + try { + ManagedType managedType = this.metamodel.managedType(value.getClass()); + return managedType != null && managedType.getPersistenceType() == PersistenceType.ENTITY; + } catch (IllegalArgumentException iae) { + // no mapped type + return false; + } + } + } } diff --git a/src/test/java/org/springframework/data/jpa/domain/sample/EmbeddedIdExampleDepartment.java b/src/test/java/org/springframework/data/jpa/domain/sample/EmbeddedIdExampleDepartment.java new file mode 100644 index 000000000..5dd7bb46b --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/domain/sample/EmbeddedIdExampleDepartment.java @@ -0,0 +1,76 @@ +/* + * 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.domain.sample; + +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class EmbeddedIdExampleDepartment { + private String name; + + @Id private Long departmentId; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Long getDepartmentId() { + return departmentId; + } + + public void setDepartmentId(Long departmentId) { + this.departmentId = departmentId; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (int) (departmentId ^ (departmentId >>> 32)); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + EmbeddedIdExampleDepartment other = (EmbeddedIdExampleDepartment) obj; + if (departmentId != other.departmentId) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } +} diff --git a/src/test/java/org/springframework/data/jpa/domain/sample/EmbeddedIdExampleEmployee.java b/src/test/java/org/springframework/data/jpa/domain/sample/EmbeddedIdExampleEmployee.java new file mode 100644 index 000000000..9fd138cce --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/domain/sample/EmbeddedIdExampleEmployee.java @@ -0,0 +1,46 @@ +/* + * 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.domain.sample; + +import javax.persistence.CascadeType; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.ManyToOne; +import javax.persistence.MapsId; + +@Entity +public class EmbeddedIdExampleEmployee { + + @EmbeddedId EmbeddedIdExampleEmployeePK employeePk; + @MapsId("departmentId") @ManyToOne(cascade = CascadeType.ALL)// + EmbeddedIdExampleDepartment department; + + public EmbeddedIdExampleEmployeePK getEmployeePk() { + return employeePk; + } + + public void setEmployeePk(EmbeddedIdExampleEmployeePK employeePk) { + this.employeePk = employeePk; + } + + public EmbeddedIdExampleDepartment getDepartment() { + return department; + } + + public void setDepartment(EmbeddedIdExampleDepartment department) { + this.department = department; + } +} diff --git a/src/test/java/org/springframework/data/jpa/domain/sample/EmbeddedIdExampleEmployeePK.java b/src/test/java/org/springframework/data/jpa/domain/sample/EmbeddedIdExampleEmployeePK.java new file mode 100644 index 000000000..f5027362e --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/domain/sample/EmbeddedIdExampleEmployeePK.java @@ -0,0 +1,77 @@ +/* + * 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.domain.sample; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Embeddable; + +@Embeddable +public class EmbeddedIdExampleEmployeePK implements Serializable { + private static final long serialVersionUID = 1L; + + @Column(nullable = false) private Long employeeId; + + @Column(nullable = false) private Long departmentId; + + public Long getEmployeeId() { + return this.employeeId; + } + + public void setEmployeeId(Long employeeId) { + this.employeeId = employeeId; + } + + public Long getDepartmentId() { + return this.departmentId; + } + + public void setDepartmentId(Long departmentId) { + this.departmentId = departmentId; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (int) (departmentId ^ (departmentId >>> 32)); + result = prime * result + (int) (employeeId ^ (employeeId >>> 32)); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + EmbeddedIdExampleEmployeePK other = (EmbeddedIdExampleEmployeePK) obj; + if (departmentId != other.departmentId) + return false; + if (employeeId != other.employeeId) + return false; + return true; + } +} diff --git a/src/test/java/org/springframework/data/jpa/domain/sample/IdClassExampleDepartment.java b/src/test/java/org/springframework/data/jpa/domain/sample/IdClassExampleDepartment.java new file mode 100644 index 000000000..c040b23fe --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/domain/sample/IdClassExampleDepartment.java @@ -0,0 +1,77 @@ +/* + * 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.domain.sample; + +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class IdClassExampleDepartment { + + private String name; + + @Id private long departmentId; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getDepartmentId() { + return departmentId; + } + + public void setDepartmentId(long departmentId) { + this.departmentId = departmentId; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (int) (departmentId ^ (departmentId >>> 32)); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + IdClassExampleDepartment other = (IdClassExampleDepartment) obj; + if (departmentId != other.departmentId) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } +} diff --git a/src/test/java/org/springframework/data/jpa/domain/sample/IdClassExampleEmployee.java b/src/test/java/org/springframework/data/jpa/domain/sample/IdClassExampleEmployee.java new file mode 100644 index 000000000..bf5be5e35 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/domain/sample/IdClassExampleEmployee.java @@ -0,0 +1,45 @@ +/* + * 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.domain.sample; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.IdClass; +import javax.persistence.ManyToOne; + +@IdClass(IdClassExampleEmployeePK.class) +@Entity +public class IdClassExampleEmployee { + + @Id long empId; + @Id @ManyToOne IdClassExampleDepartment department; + + public long getEmpId() { + return empId; + } + + public void setEmpId(long empId) { + this.empId = empId; + } + + public IdClassExampleDepartment getDepartment() { + return department; + } + + public void setDepartment(IdClassExampleDepartment department) { + this.department = department; + } +} diff --git a/src/test/java/org/springframework/data/jpa/domain/sample/IdClassExampleEmployeePK.java b/src/test/java/org/springframework/data/jpa/domain/sample/IdClassExampleEmployeePK.java new file mode 100644 index 000000000..0b874c557 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/domain/sample/IdClassExampleEmployeePK.java @@ -0,0 +1,79 @@ +/* + * 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.domain.sample; + +import java.io.Serializable; + +public class IdClassExampleEmployeePK implements Serializable { + private static final long serialVersionUID = 1L; + + private long empId; + private long department; + + public IdClassExampleEmployeePK() {} + + public long getEmpId() { + return this.empId; + } + + public void setEmpId(long empId) { + this.empId = empId; + } + + public long getDepartment() { + return this.department; + } + + public void setDepartment(long department) { + this.department = department; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (int) (department ^ (department >>> 32)); + result = prime * result + (int) (empId ^ (empId >>> 32)); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + IdClassExampleEmployeePK other = (IdClassExampleEmployeePK) obj; + if (department != other.department) { + return false; + } + if (empId != other.empId) { + return false; + } + return true; + } +} diff --git a/src/test/java/org/springframework/data/jpa/repository/DataJpa269RepositoryWithCompositeKeyTests.java b/src/test/java/org/springframework/data/jpa/repository/DataJpa269RepositoryWithCompositeKeyTests.java new file mode 100644 index 000000000..f15dbe217 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/DataJpa269RepositoryWithCompositeKeyTests.java @@ -0,0 +1,111 @@ +/* + * 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; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.data.jpa.domain.sample.EmbeddedIdExampleDepartment; +import org.springframework.data.jpa.domain.sample.EmbeddedIdExampleEmployee; +import org.springframework.data.jpa.domain.sample.EmbeddedIdExampleEmployeePK; +import org.springframework.data.jpa.domain.sample.IdClassExampleDepartment; +import org.springframework.data.jpa.domain.sample.IdClassExampleEmployee; +import org.springframework.data.jpa.domain.sample.IdClassExampleEmployeePK; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.jpa.repository.sample.EmployeeRepositoryWithEmbeddedId; +import org.springframework.data.jpa.repository.sample.EmployeeRepositoryWithIdClass; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +/** + * Tests some usage variants of composite keys with spring data jpa. + * + * @see DATAJPA-269 + * @author Thomas Darimont + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +@Transactional +public class DataJpa269RepositoryWithCompositeKeyTests { + + @Configuration + @ImportResource("classpath:infrastructure.xml") + @EnableJpaRepositories + static interface Config {} + + @Autowired EmployeeRepositoryWithIdClass employeeRepositoryWithIdClass; + @Autowired EmployeeRepositoryWithEmbeddedId employeeRepositoryWithEmbeddedId; + + /** + * @see DATAJPA-269 + * @see Final JPA 2.0 Specification 2.4.1.3 Derived Identities Example 2 + */ + @Test + public void shouldSupportSavingEntitiesWithCompositeKeyClassesWithIdClassAndDerivedIdentities() { + + IdClassExampleDepartment dep = new IdClassExampleDepartment(); + dep.setName("TestDepartment"); + dep.setDepartmentId(-1); + + IdClassExampleEmployee emp = new IdClassExampleEmployee(); + emp.setDepartment(dep); + + employeeRepositoryWithIdClass.save(emp); + + IdClassExampleEmployeePK key = new IdClassExampleEmployeePK(); + key.setDepartment(dep.getDepartmentId()); + key.setEmpId(emp.getEmpId()); + IdClassExampleEmployee persistedEmp = employeeRepositoryWithIdClass.findOne(key); + + assertThat(persistedEmp, is(notNullValue())); + assertThat(persistedEmp.getDepartment(), is(notNullValue())); + assertThat(persistedEmp.getDepartment().getName(), is(dep.getName())); + } + + /** + * @see DATAJPA-269 + * @see Final JPA 2.0 Specification 2.4.1.3 Derived Identities Example 3 + */ + @Test + public void shouldSupportSavingEntitiesWithCompositeKeyClassesWithEmbeddedIdsAndDerivedIdentities() { + + EmbeddedIdExampleDepartment dep = new EmbeddedIdExampleDepartment(); + dep.setName("TestDepartment"); + dep.setDepartmentId(-1L); + + EmbeddedIdExampleEmployee emp = new EmbeddedIdExampleEmployee(); + emp.setDepartment(dep); + emp.setEmployeePk(new EmbeddedIdExampleEmployeePK()); + + emp = employeeRepositoryWithEmbeddedId.save(emp); + + EmbeddedIdExampleEmployeePK key = new EmbeddedIdExampleEmployeePK(); + key.setDepartmentId(emp.getDepartment().getDepartmentId()); + key.setEmployeeId(emp.getEmployeePk().getEmployeeId()); + EmbeddedIdExampleEmployee persistedEmp = employeeRepositoryWithEmbeddedId.findOne(key); + + assertThat(persistedEmp, is(notNullValue())); + assertThat(persistedEmp.getDepartment(), is(notNullValue())); + assertThat(persistedEmp.getDepartment().getName(), is(dep.getName())); + + } +} diff --git a/src/test/java/org/springframework/data/jpa/repository/sample/EmployeeRepositoryWithEmbeddedId.java b/src/test/java/org/springframework/data/jpa/repository/sample/EmployeeRepositoryWithEmbeddedId.java new file mode 100644 index 000000000..7722c4861 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/sample/EmployeeRepositoryWithEmbeddedId.java @@ -0,0 +1,28 @@ +/* + * 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.sample; + +import org.springframework.data.jpa.domain.sample.EmbeddedIdExampleEmployee; +import org.springframework.data.jpa.domain.sample.EmbeddedIdExampleEmployeePK; +import org.springframework.data.jpa.repository.JpaRepository; + +/** + * Demonstrates the support for composite primary keys with {@code @EmbeddedId}. + * + * @author Thomas Darimont + */ +public interface EmployeeRepositoryWithEmbeddedId extends + JpaRepository {} diff --git a/src/test/java/org/springframework/data/jpa/repository/sample/EmployeeRepositoryWithIdClass.java b/src/test/java/org/springframework/data/jpa/repository/sample/EmployeeRepositoryWithIdClass.java new file mode 100644 index 000000000..1656fde15 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/sample/EmployeeRepositoryWithIdClass.java @@ -0,0 +1,27 @@ +/* + * 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.sample; + +import org.springframework.data.jpa.domain.sample.IdClassExampleEmployee; +import org.springframework.data.jpa.domain.sample.IdClassExampleEmployeePK; +import org.springframework.data.jpa.repository.JpaRepository; + +/** + * Demonstrates the support for composite primary keys with {@code @IdClass}. + * + * @author Thomas Darimont + */ +public interface EmployeeRepositoryWithIdClass extends JpaRepository {} diff --git a/src/test/resources/META-INF/persistence.xml b/src/test/resources/META-INF/persistence.xml index 3678b4002..397970da4 100644 --- a/src/test/resources/META-INF/persistence.xml +++ b/src/test/resources/META-INF/persistence.xml @@ -18,6 +18,11 @@ org.springframework.data.jpa.domain.sample.AbstractMappedType org.springframework.data.jpa.domain.sample.ConcreteType1 org.springframework.data.jpa.domain.sample.ConcreteType2 + org.springframework.data.jpa.domain.sample.IdClassExampleEmployee + org.springframework.data.jpa.domain.sample.IdClassExampleDepartment + org.springframework.data.jpa.domain.sample.EmbeddedIdExampleEmployeePK + org.springframework.data.jpa.domain.sample.EmbeddedIdExampleEmployee + org.springframework.data.jpa.domain.sample.EmbeddedIdExampleDepartment true