DATAJPA-50 - Introduced support for usage of @IdClass.
Introduced to support @IdClass to define entity ids. The JpeMetamodelEntityInformation builds instances of the annotated @IdClass in case any of the attributes of the entity declared in the @IdClass has a non-null value.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 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.
|
||||
@@ -17,14 +17,21 @@ package org.springframework.data.jpa.repository.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.metamodel.IdentifiableType;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.NotReadablePropertyException;
|
||||
import org.springframework.beans.NotWritablePropertyException;
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -37,13 +44,13 @@ import org.springframework.util.ReflectionUtils;
|
||||
public class JpaMetamodelEntityInformation<T, ID extends Serializable> extends JpaEntityInformationSupport<T, ID>
|
||||
implements JpaEntityInformation<T, ID> {
|
||||
|
||||
private final SingularAttribute<? super T, ?> attribute;
|
||||
private final IdMetadata<T> idMetadata;
|
||||
|
||||
/**
|
||||
* Creates a new {@link JpaMetamodelEntityInformation} for the given domain class and {@link Metamodel}.
|
||||
*
|
||||
* @param domainClass
|
||||
* @param metamodel
|
||||
* @param domainClass must not be {@literal null}.
|
||||
* @param metamodel must not be {@@iteral null}.
|
||||
*/
|
||||
public JpaMetamodelEntityInformation(Class<T> domainClass, Metamodel metamodel) {
|
||||
|
||||
@@ -60,21 +67,36 @@ public class JpaMetamodelEntityInformation<T, ID extends Serializable> extends J
|
||||
throw new IllegalArgumentException("The given domain class does not contain an id attribute!");
|
||||
}
|
||||
|
||||
IdentifiableType<T> identifiableType = (IdentifiableType<T>) type;
|
||||
this.attribute = identifiableType.getId(identifiableType.getIdType().getJavaType());
|
||||
this.idMetadata = new IdMetadata<T>((IdentifiableType<T>) type);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.IdAware#getId(java.lang.Object
|
||||
* )
|
||||
* @see org.springframework.data.repository.core.EntityInformation#getId(java.lang.Object)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ID getId(T entity) {
|
||||
|
||||
return (ID) getMemberValue(attribute.getJavaMember(), entity);
|
||||
BeanWrapper entityWrapper = new DirectFieldAccessFallbackBeanWrapper(entity);
|
||||
|
||||
if (idMetadata.hasSimpleId()) {
|
||||
return (ID) entityWrapper.getPropertyValue(idMetadata.getSimpleIdAttribute().getName());
|
||||
}
|
||||
|
||||
BeanWrapper idWrapper = new DirectFieldAccessFallbackBeanWrapper(idMetadata.getType());
|
||||
boolean partialIdValueFound = false;
|
||||
|
||||
for (SingularAttribute<? super T, ?> attribute : idMetadata) {
|
||||
Object propertyValue = entityWrapper.getPropertyValue(attribute.getName());
|
||||
|
||||
if (propertyValue != null) {
|
||||
partialIdValueFound = true;
|
||||
}
|
||||
|
||||
idWrapper.setPropertyValue(attribute.getName(), propertyValue);
|
||||
}
|
||||
|
||||
return (ID) (partialIdValueFound ? idWrapper.getWrappedInstance() : null);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -85,30 +107,7 @@ public class JpaMetamodelEntityInformation<T, ID extends Serializable> extends J
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<ID> getIdType() {
|
||||
|
||||
return (Class<ID>) attribute.getJavaType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the given {@link Member} of the given {@link Object} .
|
||||
*
|
||||
* @param member
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
private static Object getMemberValue(Member member, Object source) {
|
||||
|
||||
if (member instanceof Field) {
|
||||
Field field = (Field) member;
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
return ReflectionUtils.getField(field, source);
|
||||
} else if (member instanceof Method) {
|
||||
Method method = (Method) member;
|
||||
ReflectionUtils.makeAccessible(method);
|
||||
return ReflectionUtils.invokeMethod(method, source);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Given member is neither Field nor Method!");
|
||||
return (Class<ID>) idMetadata.getType();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -118,7 +117,99 @@ public class JpaMetamodelEntityInformation<T, ID extends Serializable> extends J
|
||||
* getIdAttribute()
|
||||
*/
|
||||
public SingularAttribute<? super T, ?> getIdAttribute() {
|
||||
return idMetadata.getSimpleIdAttribute();
|
||||
}
|
||||
|
||||
return attribute;
|
||||
/**
|
||||
* Simple value object to encapsulate id specific metadata.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class IdMetadata<T> implements Iterable<SingularAttribute<? super T, ?>> {
|
||||
|
||||
private final IdentifiableType<T> type;
|
||||
private final Set<SingularAttribute<? super T, ?>> attributes;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public IdMetadata(IdentifiableType<T> source) {
|
||||
|
||||
this.type = source;
|
||||
this.attributes = (Set<SingularAttribute<? super T, ?>>) (source.hasSingleIdAttribute() ? Collections
|
||||
.singleton(source.getId(source.getIdType().getJavaType())) : source.getIdClassAttributes());
|
||||
}
|
||||
|
||||
public boolean hasSimpleId() {
|
||||
return attributes.size() == 1;
|
||||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
|
||||
try {
|
||||
return type.getIdType().getJavaType();
|
||||
} catch (IllegalStateException e) {
|
||||
// see https://hibernate.onjira.com/browse/HHH-6951
|
||||
IdClass annotation = type.getJavaType().getAnnotation(IdClass.class);
|
||||
return annotation == null ? null : annotation.value();
|
||||
}
|
||||
}
|
||||
|
||||
public SingularAttribute<? super T, ?> getSimpleIdAttribute() {
|
||||
return attributes.iterator().next();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Iterable#iterator()
|
||||
*/
|
||||
public Iterator<SingularAttribute<? super T, ?>> iterator() {
|
||||
return attributes.iterator();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom extension of {@link BeanWrapperImpl} that falls back to direct field access in case the object or type being
|
||||
* wrapped does not use accessor methods.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class DirectFieldAccessFallbackBeanWrapper extends BeanWrapperImpl {
|
||||
|
||||
public DirectFieldAccessFallbackBeanWrapper(Object entity) {
|
||||
super(entity);
|
||||
}
|
||||
|
||||
public DirectFieldAccessFallbackBeanWrapper(Class<?> type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.BeanWrapperImpl#getPropertyValue(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Object getPropertyValue(String propertyName) throws BeansException {
|
||||
try {
|
||||
return super.getPropertyValue(propertyName);
|
||||
} catch (NotReadablePropertyException e) {
|
||||
Field field = ReflectionUtils.findField(getWrappedClass(), propertyName);
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
return ReflectionUtils.getField(field, getWrappedInstance());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.BeanWrapperImpl#setPropertyValue(java.lang.String, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public void setPropertyValue(String propertyName, Object value) throws BeansException {
|
||||
try {
|
||||
super.setPropertyValue(propertyName, value);
|
||||
} catch (NotWritablePropertyException e) {
|
||||
Field field = ReflectionUtils.findField(getWrappedClass(), propertyName);
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
ReflectionUtils.setField(field, getWrappedInstance(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008-2011 the original author or authors.
|
||||
* Copyright 2008-2012 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.
|
||||
@@ -195,16 +195,20 @@ public class SimpleJpaRepository<T, ID extends Serializable> implements JpaRepos
|
||||
|
||||
Assert.notNull(id, "The given id must not be null!");
|
||||
|
||||
String placeholder = provider.getCountQueryPlaceholder();
|
||||
String entityName = entityInformation.getEntityName();
|
||||
String idAttributeName = entityInformation.getIdAttribute().getName();
|
||||
if (entityInformation.getIdAttribute() != null) {
|
||||
|
||||
String existsQuery = String.format(EXISTS_QUERY_STRING, placeholder, entityName, idAttributeName);
|
||||
String placeholder = provider.getCountQueryPlaceholder();
|
||||
String entityName = entityInformation.getEntityName();
|
||||
String idAttributeName = entityInformation.getIdAttribute().getName();
|
||||
String existsQuery = String.format(EXISTS_QUERY_STRING, placeholder, entityName, idAttributeName);
|
||||
|
||||
TypedQuery<Long> query = em.createQuery(existsQuery, Long.class);
|
||||
query.setParameter("id", id);
|
||||
TypedQuery<Long> query = em.createQuery(existsQuery, Long.class);
|
||||
query.setParameter("id", id);
|
||||
|
||||
return query.getSingleResult() == 1;
|
||||
return query.getSingleResult() == 1;
|
||||
} else {
|
||||
return findOne(id) != null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2012 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 org.springframework.data.domain.Persistable;
|
||||
|
||||
/**
|
||||
* Sample entity using {@link IdClass} annotation to demarcate ids.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Entity
|
||||
@IdClass(SampleWithIdClassPK.class)
|
||||
public class SampleWithIdClass implements Persistable<SampleWithIdClassPK> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
Long first;
|
||||
|
||||
@Id
|
||||
Long second;
|
||||
|
||||
private boolean isNew;
|
||||
|
||||
protected SampleWithIdClass() {
|
||||
this.isNew = true;
|
||||
}
|
||||
|
||||
public SampleWithIdClass(Long first, Long second) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
this.isNew = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the first
|
||||
*/
|
||||
public Long getFirst() {
|
||||
return first;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the second
|
||||
*/
|
||||
public Long getSecond() {
|
||||
return second;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.domain.Persistable#getId()
|
||||
*/
|
||||
public SampleWithIdClassPK getId() {
|
||||
return new SampleWithIdClassPK(first, second);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.domain.Persistable#isNew()
|
||||
*/
|
||||
public boolean isNew() {
|
||||
return this.isNew;
|
||||
}
|
||||
|
||||
public void setNotNew() {
|
||||
this.isNew = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2012 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 static org.springframework.util.ObjectUtils.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class SampleWithIdClassPK implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 23126782341L;
|
||||
|
||||
private Long first;
|
||||
private Long second;
|
||||
|
||||
public SampleWithIdClassPK() {
|
||||
|
||||
}
|
||||
|
||||
public SampleWithIdClassPK(Long first, Long second) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
public void setFirst(Long first) {
|
||||
this.first = first;
|
||||
}
|
||||
|
||||
public void setSecond(Long second) {
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj == null || !(obj.getClass().equals(getClass()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SampleWithIdClassPK that = (SampleWithIdClassPK) obj;
|
||||
|
||||
return nullSafeEquals(this.first, that.first) && nullSafeEquals(this.second, that.second);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int result = 17;
|
||||
|
||||
result += nullSafeHashCode(this.first);
|
||||
result += nullSafeHashCode(this.second);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2011-2012 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.
|
||||
@@ -28,7 +28,10 @@ import javax.persistence.metamodel.Metamodel;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
import org.springframework.data.jpa.domain.sample.SampleWithIdClass;
|
||||
import org.springframework.data.jpa.domain.sample.SampleWithIdClassPK;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@@ -62,4 +65,31 @@ public class JpaMetamodelEntityInformationIntegrationTests {
|
||||
JpaEntityInformation<?, ?> information = JpaEntityInformationSupport.getMetadata(AbstractPersistable.class, em);
|
||||
assertEquals(Serializable.class, information.getIdType());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-50
|
||||
*/
|
||||
@Test
|
||||
public void detectsIdClass() {
|
||||
|
||||
EntityInformation<SampleWithIdClass, ?> information = JpaEntityInformationSupport.getMetadata(
|
||||
SampleWithIdClass.class, em);
|
||||
assertThat(information.getIdType(), is(typeCompatibleWith(SampleWithIdClassPK.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-50
|
||||
*/
|
||||
@Test
|
||||
public void returnsIdInstanceCorrectly() {
|
||||
|
||||
SampleWithIdClass entity = new SampleWithIdClass(2L, 4L);
|
||||
|
||||
JpaEntityInformation<SampleWithIdClass, ?> information = JpaEntityInformationSupport.getMetadata(
|
||||
SampleWithIdClass.class, em);
|
||||
Object id = information.getId(entity);
|
||||
|
||||
assertThat(id, is(SampleWithIdClassPK.class));
|
||||
assertThat(id, is((Object) new SampleWithIdClassPK(2L, 4L)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2012 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 java.util.Arrays.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.metamodel.IdentifiableType;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
import javax.persistence.metamodel.Type;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.jpa.domain.sample.SampleWithIdClass;
|
||||
import org.springframework.data.jpa.domain.sample.SampleWithIdClassPK;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link JpaMetamodelEntityInformation}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JpaMetamodelEntityInformationUnitTest {
|
||||
|
||||
@Mock
|
||||
Metamodel metamodel;
|
||||
|
||||
@Mock
|
||||
IdentifiableType<SampleWithIdClass> type;
|
||||
@Mock
|
||||
SingularAttribute<SampleWithIdClass, ?> first, second;
|
||||
|
||||
@Mock
|
||||
@SuppressWarnings("rawtypes")
|
||||
Type idType;
|
||||
|
||||
@Before
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setUp() {
|
||||
|
||||
when(first.getName()).thenReturn("first");
|
||||
when(second.getName()).thenReturn("second");
|
||||
Set<SingularAttribute<? super SampleWithIdClass, ?>> attributes = new HashSet<SingularAttribute<? super SampleWithIdClass, ?>>(
|
||||
asList(first, second));
|
||||
|
||||
when(type.getIdClassAttributes()).thenReturn(attributes);
|
||||
|
||||
when(metamodel.managedType(SampleWithIdClass.class)).thenReturn(type);
|
||||
|
||||
when(type.getIdType()).thenReturn(idType);
|
||||
when(idType.getJavaType()).thenReturn(SampleWithIdClassPK.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-50
|
||||
*/
|
||||
@Test
|
||||
public void doesNotCreateIdIfAllPartialAttributesAreNull() {
|
||||
|
||||
JpaMetamodelEntityInformation<SampleWithIdClass, Serializable> information = new JpaMetamodelEntityInformation<SampleWithIdClass, Serializable>(
|
||||
SampleWithIdClass.class, metamodel);
|
||||
|
||||
SampleWithIdClass entity = new SampleWithIdClass(null, null);
|
||||
assertThat(information.getId(entity), is(nullValue()));
|
||||
|
||||
entity = new SampleWithIdClass(2L, null);
|
||||
assertThat(information.getId(entity), is(notNullValue()));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008-2011 the original author or authors.
|
||||
* Copyright 2008-2012 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.
|
||||
@@ -28,7 +28,10 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.data.jpa.domain.sample.SampleEntity;
|
||||
import org.springframework.data.jpa.domain.sample.SampleEntityPK;
|
||||
import org.springframework.data.jpa.domain.sample.SampleWithIdClass;
|
||||
import org.springframework.data.jpa.domain.sample.SampleWithIdClassPK;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -47,11 +50,13 @@ public class JpaRepositoryTests {
|
||||
EntityManager em;
|
||||
|
||||
JpaRepository<SampleEntity, SampleEntityPK> repository;
|
||||
CrudRepository<SampleWithIdClass, SampleWithIdClassPK> idClassRepository;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
repository = new JpaRepositoryFactory(em).getRepository(SampleEntityRepository.class);
|
||||
idClassRepository = new JpaRepositoryFactory(em).getRepository(SampleWithIdClassRepository.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -68,7 +73,28 @@ public class JpaRepositoryTests {
|
||||
assertThat(repository.count(), is(0L));
|
||||
}
|
||||
|
||||
/**
|
||||
* DATAJPA-50
|
||||
*/
|
||||
@Test
|
||||
public void executesCrudOperationsForEntityWithIdClass() {
|
||||
|
||||
SampleWithIdClass entity = new SampleWithIdClass(1L, 1L);
|
||||
idClassRepository.save(entity);
|
||||
|
||||
assertThat(entity.getFirst(), is(notNullValue()));
|
||||
assertThat(entity.getSecond(), is(notNullValue()));
|
||||
|
||||
SampleWithIdClassPK id = new SampleWithIdClassPK(entity.getFirst(), entity.getSecond());
|
||||
|
||||
assertThat(idClassRepository.findOne(id), is(entity));
|
||||
}
|
||||
|
||||
private static interface SampleEntityRepository extends JpaRepository<SampleEntity, SampleEntityPK> {
|
||||
|
||||
}
|
||||
|
||||
private static interface SampleWithIdClassRepository extends CrudRepository<SampleWithIdClass, SampleWithIdClassPK> {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<class>org.springframework.data.jpa.domain.sample.AuditableRole</class>
|
||||
<class>org.springframework.data.jpa.domain.sample.SampleEntity</class>
|
||||
<class>org.springframework.data.jpa.domain.sample.SampleEntityPK</class>
|
||||
<class>org.springframework.data.jpa.domain.sample.SampleWithIdClass</class>
|
||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||
</persistence-unit>
|
||||
<persistence-unit name="querydsl">
|
||||
|
||||
Reference in New Issue
Block a user