DATAJPA-12 - Design changes in JpaSort.
Decided to go with a simpler way of building up attribute paths on JpaSort to avoid the need to work with JPA Path instances (and thus the EntityManager) entirely. Added shortcut constructors to JpaSort that take a vararg of Attribute or PluralAttribute respectively. Interestingly, the test cases still have to be integration tests as the fields in the statically generated meta-model are null until the EntityManagerFactory bootstrap process enhances them to contain actual values. So no real unit tests unfortunately. Consolidated tests cases for MailMessageRepository into one class, especially to avoid the configuration QueryDslRepositorySupportIntegrationTests to interfere with the newly added tests. Also rather use SampleConfig configuration class to allow the test framework's caching mechanism to kick in. Original pull request: #54.
This commit is contained in:
@@ -17,172 +17,114 @@ package org.springframework.data.jpa.domain;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.jpa.support.JpaMetaModelPathBuilder.*;
|
||||
import static org.springframework.data.jpa.domain.JpaSort.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Path;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.PluralAttribute;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.jpa.domain.sample.Address_;
|
||||
import org.springframework.data.jpa.domain.sample.MailMessage_;
|
||||
import org.springframework.data.jpa.domain.sample.MailSender_;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.domain.sample.User_;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Unit test for {@link JpaSort}.
|
||||
* Integration tests for {@link JpaSort}. This has to be an integration test due to the design of the statically
|
||||
* generated meta-model classes. The properties cannot be referred to statically (quite a surprise, as they're static)
|
||||
* but only after they've been enhanced by the persistence provider. This requires an {@link EntityManagerFactory} to be
|
||||
* bootstrapped.
|
||||
*
|
||||
* @see DATAJPA-12
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@ContextConfiguration("classpath:infrastructure.xml")
|
||||
public class JpaSortTests {
|
||||
|
||||
@Configuration
|
||||
@ImportResource("classpath:infrastructure.xml")
|
||||
static class Config {}
|
||||
private static final Attribute<?, ?> NULL_ATTRIBUTE = null;
|
||||
private static final Attribute<?, ?>[] EMPTY_ATTRIBUTES = new Attribute<?, ?>[0];
|
||||
|
||||
@PersistenceContext EntityManager em;
|
||||
private static final PluralAttribute<?, ?, ?> NULL_PLURAL_ATTRIBUTE = null;
|
||||
private static final PluralAttribute<?, ?, ?>[] EMPTY_PLURAL_ATTRIBUTES = new PluralAttribute<?, ?, ?>[0];
|
||||
|
||||
private static final MailMessage_ jmail = null;
|
||||
private static final MailSender_ jsender = null;
|
||||
|
||||
/**
|
||||
* @see DATAJPA-12
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldThrowIfNoOrderSpecifiersAreGiven() {
|
||||
new JpaSort();
|
||||
public void rejectsNullAttribute() {
|
||||
new JpaSort(NULL_ATTRIBUTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-12
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldThrowIfNullIsGiven() {
|
||||
new JpaSort((List<Path<?>>) null);
|
||||
public void rejectsEmptyAttributes() {
|
||||
new JpaSort(EMPTY_ATTRIBUTES);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullPluralAttribute() {
|
||||
new JpaSort(NULL_PLURAL_ATTRIBUTE);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsEmptyPluralAttributes() {
|
||||
new JpaSort(EMPTY_PLURAL_ATTRIBUTES);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-12
|
||||
*/
|
||||
@Test
|
||||
public void sortBySinglePropertyWithDefaultSortDirection() {
|
||||
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
CriteriaQuery<User> q = cb.createQuery(User.class);
|
||||
Root<User> c = q.from(User.class);
|
||||
|
||||
JpaSort sort = new JpaSort(c.get("firstname"));
|
||||
|
||||
assertThat(sort, hasItems(new Sort.Order("firstname")));
|
||||
assertThat(new JpaSort(path(User_.firstname)), hasItems(new Sort.Order("firstname")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-12
|
||||
*/
|
||||
@Test
|
||||
public void sortByMultiplePropertiesWithDefaultSortDirection() {
|
||||
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
CriteriaQuery<User> q = cb.createQuery(User.class);
|
||||
Root<User> c = q.from(User.class);
|
||||
|
||||
JpaSort sort = new JpaSort(c.get("firstname"), c.get("lastname"));
|
||||
assertThat(sort, hasItems(new Sort.Order("firstname"), new Sort.Order("lastname")));
|
||||
assertThat(new JpaSort(User_.firstname, User_.lastname),
|
||||
hasItems(new Sort.Order("firstname"), new Sort.Order("lastname")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-12
|
||||
*/
|
||||
@Test
|
||||
public void sortByMultiplePropertiesWithDescSortDirection() {
|
||||
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
CriteriaQuery<User> q = cb.createQuery(User.class);
|
||||
Root<User> c = q.from(User.class);
|
||||
|
||||
JpaSort sort = new JpaSort(Direction.DESC, c.get("firstname"), c.get("lastname"));
|
||||
|
||||
assertThat(sort, hasItems(new Sort.Order(Direction.DESC, "firstname"), new Sort.Order(Direction.DESC, "lastname")));
|
||||
assertThat(new JpaSort(Direction.DESC, User_.firstname, User_.lastname),
|
||||
hasItems(new Sort.Order(Direction.DESC, "firstname"), new Sort.Order(Direction.DESC, "lastname")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-12
|
||||
*/
|
||||
@Test
|
||||
public void combiningSortByMultipleProperties() {
|
||||
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
CriteriaQuery<User> q = cb.createQuery(User.class);
|
||||
Root<User> c = q.from(User.class);
|
||||
|
||||
Sort sort = new JpaSort(c.get("firstname")).and(new JpaSort(c.get("lastname")));
|
||||
|
||||
assertThat(sort, hasItems(new Sort.Order("firstname"), new Sort.Order("lastname")));
|
||||
assertThat(new JpaSort(User_.firstname).and(new JpaSort(User_.lastname)),
|
||||
hasItems(new Sort.Order("firstname"), new Sort.Order("lastname")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-12
|
||||
*/
|
||||
@Test
|
||||
public void combiningSortByMultiplePropertiesWithDifferentSort() {
|
||||
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
CriteriaQuery<User> q = cb.createQuery(User.class);
|
||||
Root<User> c = q.from(User.class);
|
||||
|
||||
Sort sort = new JpaSort(c.get("firstname")).and(new JpaSort(Direction.DESC, c.get("lastname")));
|
||||
|
||||
assertThat(sort, hasItems(new Sort.Order("firstname"), new Sort.Order(Direction.DESC, "lastname")));
|
||||
assertThat(new JpaSort(User_.firstname).and(new JpaSort(Direction.DESC, User_.lastname)),
|
||||
hasItems(new Sort.Order("firstname"), new Sort.Order(Direction.DESC, "lastname")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-12
|
||||
*/
|
||||
@Test
|
||||
public void combiningSortByNestedEmbeddedProperty() {
|
||||
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
CriteriaQuery<User> q = cb.createQuery(User.class);
|
||||
Root<User> c = q.from(User.class);
|
||||
|
||||
Sort sort = new JpaSort(c.get("address").get("streetName"));
|
||||
|
||||
assertThat(sort, hasItems(new Sort.Order("address.streetName")));
|
||||
assertThat(new JpaSort(path(User_.address).dot(Address_.streetName)),
|
||||
hasItems(new Sort.Order("address.streetName")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-12
|
||||
*/
|
||||
@Test
|
||||
public void buildJpaSortFromJpaMetaModelSingleAttribute() {
|
||||
|
||||
Sort sort = new JpaSort(Direction.ASC, path(User_.firstname).build(em));
|
||||
|
||||
assertThat(sort, hasItems(new Sort.Order("firstname")));
|
||||
assertThat(new JpaSort(Direction.ASC, path(User_.firstname)), //
|
||||
hasItems(new Sort.Order("firstname")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-12
|
||||
*/
|
||||
@Test
|
||||
public void buildJpaSortFromJpaMetaModelNestedAttribute() {
|
||||
|
||||
Sort sort = new JpaSort(Direction.ASC, path(MailMessage_.mailSender).get(MailSender_.name).build(em));
|
||||
|
||||
assertThat(sort, hasItems(new Sort.Order("mailSender.name")));
|
||||
assertThat(new JpaSort(Direction.ASC, path(MailMessage_.mailSender).dot(MailSender_.name)),
|
||||
hasItems(new Sort.Order("mailSender.name")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,18 +17,13 @@ package org.springframework.data.jpa.repository.support;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.jpa.support.JpaMetaModelPathBuilder.*;
|
||||
import static org.springframework.data.jpa.domain.JpaSort.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
|
||||
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.Import;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
@@ -37,30 +32,27 @@ import org.springframework.data.jpa.domain.sample.MailMessage;
|
||||
import org.springframework.data.jpa.domain.sample.MailMessage_;
|
||||
import org.springframework.data.jpa.domain.sample.MailSender;
|
||||
import org.springframework.data.jpa.domain.sample.MailSender_;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.data.jpa.repository.config.InfrastructureConfig;
|
||||
import org.springframework.data.jpa.domain.sample.QMailMessage;
|
||||
import org.springframework.data.jpa.domain.sample.QMailSender;
|
||||
import org.springframework.data.jpa.repository.sample.MailMessageRepository;
|
||||
import org.springframework.data.jpa.repository.sample.SampleConfig;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link MailMessageRepository}.
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Transactional
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class JpaMetaModelRepositoryUnitTests {
|
||||
@ContextConfiguration(classes = SampleConfig.class)
|
||||
@Transactional
|
||||
public class MailMessageRepositoryIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
@Import(InfrastructureConfig.class)
|
||||
@EnableJpaRepositories(basePackageClasses = MailMessageRepository.class)
|
||||
static class Config {}
|
||||
|
||||
private static final MailMessage_ jmail = null;
|
||||
private static final MailSender_ jsender = null;
|
||||
|
||||
@PersistenceContext EntityManager em;
|
||||
static final QMailMessage message = QMailMessage.mailMessage;
|
||||
static final QMailSender sender = QMailSender.mailSender;
|
||||
|
||||
@Autowired MailMessageRepository mailMessageRepository;
|
||||
|
||||
@@ -82,11 +74,35 @@ public class JpaMetaModelRepositoryUnitTests {
|
||||
mailMessageRepository.save(message2);
|
||||
|
||||
Page<MailMessage> results = mailMessageRepository.findAll(new PageRequest(0, 20, //
|
||||
new JpaSort(Direction.ASC, path(jmail.mailSender).get(jsender.name).build(em))));
|
||||
new JpaSort(Direction.ASC, path(MailMessage_.mailSender).dot(MailSender_.name))));
|
||||
List<MailMessage> messages = results.getContent();
|
||||
|
||||
assertThat(messages, hasSize(2));
|
||||
assertThat(messages.get(0).getMailSender(), is(nullValue()));
|
||||
assertThat(messages.get(1).getMailSender(), is(sender1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-12
|
||||
*/
|
||||
@Test
|
||||
public void shouldSortMailWithQueryDslRepositoryAndDslSortCriteriaNullsFirst() {
|
||||
|
||||
MailMessage message1 = new MailMessage();
|
||||
message1.setContent("abc");
|
||||
MailSender sender1 = new MailSender("foo");
|
||||
message1.setMailSender(sender1);
|
||||
|
||||
MailMessage message2 = new MailMessage();
|
||||
message2.setContent("abc");
|
||||
|
||||
mailMessageRepository.save(message1);
|
||||
mailMessageRepository.save(message2);
|
||||
|
||||
List<MailMessage> messages = mailMessageRepository.findAll(message.content.eq("abc"), message.mailSender.name.asc());
|
||||
|
||||
assertThat(messages, hasSize(2));
|
||||
assertThat(messages.get(0).getMailSender(), is(nullValue()));
|
||||
assertThat(messages.get(1).getMailSender(), is(sender1));
|
||||
}
|
||||
}
|
||||
@@ -18,8 +18,6 @@ package org.springframework.data.jpa.repository.support;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
|
||||
@@ -27,21 +25,11 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.jpa.domain.sample.MailMessage;
|
||||
import org.springframework.data.jpa.domain.sample.MailSender;
|
||||
import org.springframework.data.jpa.domain.sample.QMailMessage;
|
||||
import org.springframework.data.jpa.domain.sample.QMailSender;
|
||||
import org.springframework.data.jpa.domain.sample.User;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.data.jpa.repository.config.InfrastructureConfig;
|
||||
import org.springframework.data.jpa.repository.sample.MailMessageRepository;
|
||||
import org.springframework.data.jpa.repository.support.QueryDslRepositorySupportTests.UserRepository;
|
||||
import org.springframework.data.jpa.repository.support.QueryDslRepositorySupportTests.UserRepositoryImpl;
|
||||
import org.springframework.data.querydsl.QPageRequest;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@@ -60,13 +48,10 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
public class QueryDslRepositorySupportIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableJpaRepositories(basePackageClasses = MailMessageRepository.class, includeFilters = @Filter(
|
||||
type = FilterType.ASSIGNABLE_TYPE, value = { MailMessageRepository.class }))
|
||||
@EnableTransactionManagement
|
||||
static class Config extends InfrastructureConfig {
|
||||
@Bean
|
||||
public UserRepositoryImpl userRepositoryImpl() {
|
||||
|
||||
return new UserRepositoryImpl() {
|
||||
@Override
|
||||
@PersistenceContext(unitName = "querydsl")
|
||||
@@ -86,6 +71,7 @@ public class QueryDslRepositorySupportIntegrationTests {
|
||||
return new EntityManagerContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
|
||||
@@ -96,16 +82,10 @@ public class QueryDslRepositorySupportIntegrationTests {
|
||||
}
|
||||
|
||||
@Autowired UserRepository repository;
|
||||
|
||||
@Autowired ReconfiguringUserRepositoryImpl reconfiguredRepo;
|
||||
|
||||
@Autowired MailMessageRepository mailMessageRepository;
|
||||
|
||||
@PersistenceContext(unitName = "querydsl") EntityManager em;
|
||||
|
||||
static final QMailMessage qmail = QMailMessage.mailMessage;
|
||||
static final QMailSender qsender = QMailSender.mailSender;
|
||||
|
||||
@Test
|
||||
public void createsRepoCorrectly() {
|
||||
assertThat(repository, is(notNullValue()));
|
||||
@@ -121,56 +101,6 @@ public class QueryDslRepositorySupportIntegrationTests {
|
||||
assertThat(reconfiguredRepo.getEntityManager().getEntityManagerFactory(), is(em.getEntityManagerFactory()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-12
|
||||
*/
|
||||
@Test
|
||||
public void shouldSortMailWithQueryDslRepositoryAndQPageRequestDslSortCriteriaNullsFirst() {
|
||||
|
||||
MailMessage message1 = new MailMessage();
|
||||
message1.setContent("abc");
|
||||
MailSender sender1 = new MailSender("foo");
|
||||
message1.setMailSender(sender1);
|
||||
|
||||
MailMessage message2 = new MailMessage();
|
||||
message2.setContent("abc");
|
||||
|
||||
mailMessageRepository.save(message1);
|
||||
mailMessageRepository.save(message2);
|
||||
|
||||
Page<MailMessage> results = mailMessageRepository.findAll(qmail.content.eq("abc"), new QPageRequest(0, 20,
|
||||
qsender.name.asc()));
|
||||
List<MailMessage> messages = results.getContent();
|
||||
|
||||
assertThat(messages, hasSize(2));
|
||||
assertThat(messages.get(0).getMailSender(), is(nullValue()));
|
||||
assertThat(messages.get(1).getMailSender(), is(sender1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-12
|
||||
*/
|
||||
@Test
|
||||
public void shouldSortMailWithQueryDslRepositoryAndDslSortCriteriaNullsFirst() {
|
||||
|
||||
MailMessage message1 = new MailMessage();
|
||||
message1.setContent("abc");
|
||||
MailSender sender1 = new MailSender("foo");
|
||||
message1.setMailSender(sender1);
|
||||
|
||||
MailMessage message2 = new MailMessage();
|
||||
message2.setContent("abc");
|
||||
|
||||
mailMessageRepository.save(message1);
|
||||
mailMessageRepository.save(message2);
|
||||
|
||||
List<MailMessage> messages = mailMessageRepository.findAll(qmail.content.eq("abc"), qmail.mailSender.name.asc());
|
||||
|
||||
assertThat(messages, hasSize(2));
|
||||
assertThat(messages.get(0).getMailSender(), is(nullValue()));
|
||||
assertThat(messages.get(1).getMailSender(), is(sender1));
|
||||
}
|
||||
|
||||
static class ReconfiguringUserRepositoryImpl extends QueryDslRepositorySupport {
|
||||
|
||||
public ReconfiguringUserRepositoryImpl() {
|
||||
|
||||
Reference in New Issue
Block a user