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.
This commit is contained in:
committed by
Oliver Gierke
parent
5e5f494ac5
commit
6824cc158e
@@ -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<T, ID extends Serializable> extends J
|
||||
|
||||
private final IdMetadata<T> idMetadata;
|
||||
private final SingularAttribute<? super T, ?> 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<T, ID extends Serializable> extends J
|
||||
super(domainClass);
|
||||
|
||||
Assert.notNull(metamodel);
|
||||
this.metamodel = metamodel;
|
||||
|
||||
ManagedType<T> type = metamodel.managedType(domainClass);
|
||||
|
||||
if (type == null) {
|
||||
@@ -106,7 +110,7 @@ public class JpaMetamodelEntityInformation<T, ID extends Serializable> 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<? super T, ?> attribute : idMetadata) {
|
||||
@@ -291,4 +295,67 @@ public class JpaMetamodelEntityInformation<T, ID extends Serializable> 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<? extends Object> managedType = this.metamodel.managedType(value.getClass());
|
||||
return managedType != null && managedType.getPersistenceType() == PersistenceType.ENTITY;
|
||||
} catch (IllegalArgumentException iae) {
|
||||
// no mapped type
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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()));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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<EmbeddedIdExampleEmployee, EmbeddedIdExampleEmployeePK> {}
|
||||
@@ -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<IdClassExampleEmployee, IdClassExampleEmployeePK> {}
|
||||
@@ -18,6 +18,11 @@
|
||||
<class>org.springframework.data.jpa.domain.sample.AbstractMappedType</class>
|
||||
<class>org.springframework.data.jpa.domain.sample.ConcreteType1</class>
|
||||
<class>org.springframework.data.jpa.domain.sample.ConcreteType2</class>
|
||||
<class>org.springframework.data.jpa.domain.sample.IdClassExampleEmployee</class>
|
||||
<class>org.springframework.data.jpa.domain.sample.IdClassExampleDepartment</class>
|
||||
<class>org.springframework.data.jpa.domain.sample.EmbeddedIdExampleEmployeePK</class>
|
||||
<class>org.springframework.data.jpa.domain.sample.EmbeddedIdExampleEmployee</class>
|
||||
<class>org.springframework.data.jpa.domain.sample.EmbeddedIdExampleDepartment</class>
|
||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||
</persistence-unit>
|
||||
<persistence-unit name="querydsl">
|
||||
|
||||
Reference in New Issue
Block a user