DATAREST-883 - Consider Jackson field names in Sort mapping.

We now consider Jackson field names when resolving Sort arguments. Domain model properties annotated with @JsonProperty("sales") can be specified by their Jackson-mapped field name in sort arguments. Field names are mapped to their according persistent property names to be used in repository query method sorting. Unknown field names are silently dropped.

Original pull request: #222.
This commit is contained in:
Mark Paluch
2016-09-05 12:39:45 +02:00
committed by Oliver Gierke
parent bacd8be4fc
commit a999bd3ca8
13 changed files with 798 additions and 78 deletions

View File

@@ -26,8 +26,11 @@ import javax.persistence.ManyToMany;
import org.springframework.data.rest.core.annotation.RestResource;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* @author Oliver Gierke
* @author Mark Paluch
*/
@Entity
public class Book {
@@ -35,16 +38,20 @@ public class Book {
public @Id @GeneratedValue Long id;
public String isbn, title;
@JsonProperty("sales")
public long soldUnits;
@ManyToMany(cascade = { CascadeType.MERGE }) //
@RestResource(path = "creators") //
public Set<Author> authors;
protected Book() {}
public Book(String isbn, String title, Iterable<Author> authors) {
public Book(String isbn, String title, long soldUnits, Iterable<Author> authors) {
this.isbn = isbn;
this.title = title;
this.soldUnits = soldUnits;
this.authors = new HashSet<Author>();

View File

@@ -17,6 +17,8 @@ package org.springframework.data.rest.webmvc.jpa;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
@@ -26,6 +28,7 @@ import org.springframework.data.rest.core.annotation.RestResource;
/**
* @author Oliver Gierke
* @author Mark Paluch
*/
@RepositoryRestResource(excerptProjection = BookExcerpt.class)
public interface BookRepository extends CrudRepository<Book, Long> {
@@ -35,4 +38,8 @@ public interface BookRepository extends CrudRepository<Book, Long> {
@Query("select b from Book b where :author member of b.authors")
List<Book> findByAuthorsContains(@Param("author") Author author);
@RestResource(rel = "find-spring-books-sorted")
@Query("select b from Book b where b.title like 'Spring%'")
Page<Book> findByTitleIsLike(Pageable pageable);
}

View File

@@ -20,6 +20,7 @@ import static org.junit.Assert.*;
import static org.springframework.data.rest.webmvc.util.TestUtils.*;
import static org.springframework.http.HttpHeaders.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import net.minidev.json.JSONArray;
@@ -57,6 +58,7 @@ import com.jayway.jsonpath.JsonPath;
*
* @author Oliver Gierke
* @author Greg Turnquist
* @author Mark Paluch
*/
@Transactional
@ContextConfiguration(classes = JpaRepositoryConfig.class)
@@ -546,7 +548,7 @@ public class JpaWebTests extends CommonWebTests {
* @see DATAREST-384
*/
@Test
public void execturesSearchThatTakesASort() throws Exception {
public void exectuesSearchThatTakesASort() throws Exception {
Link booksLink = client.discoverUnique("books");
Link searchLink = client.discoverUnique(booksLink, "search");
@@ -568,6 +570,57 @@ public class JpaWebTests extends CommonWebTests {
andExpect(client.hasLinkWithRel("self"));
}
/**
* @see DATAREST-883
*/
@Test
public void exectuesSearchThatTakesAMappedSortProperty() throws Exception {
Link booksLink = client.discoverUnique("books");
Link searchLink = client.discoverUnique(booksLink, "search");
Link findBySortedLink = client.discoverUnique(searchLink, "find-by-sorted");
// Assert sort options advertised
assertThat(findBySortedLink.isTemplated(), is(true));
assertThat(findBySortedLink.getVariableNames(), hasItems("sort", "projection"));
// Assert results returned as specified
client.follow(findBySortedLink.expand("sales,desc")).//
andExpect(jsonPath("$._embedded.books[0].title").value("Spring Data (Second Edition)")).//
andExpect(jsonPath("$._embedded.books[1].title").value("Spring Data")).//
andExpect(client.hasLinkWithRel("self"));
client.follow(findBySortedLink.expand("sales,asc")).//
andExpect(jsonPath("$._embedded.books[0].title").value("Spring Data")).//
andExpect(jsonPath("$._embedded.books[1].title").value("Spring Data (Second Edition)")).//
andExpect(client.hasLinkWithRel("self"));
}
/**
* @see DATAREST-883
*/
@Test
public void exectuesCustomQuerySearchThatTakesAMappedSortProperty() throws Exception {
Link booksLink = client.discoverUnique("books");
Link searchLink = client.discoverUnique(booksLink, "search");
Link findByLink = client.discoverUnique(searchLink, "find-spring-books-sorted");
// Assert sort options advertised
assertThat(findByLink.isTemplated(), is(true));
// Assert results returned as specified
client.follow(findByLink.expand("0", "10", "sales,desc")).//
andExpect(jsonPath("$._embedded.books[0].title").value("Spring Data (Second Edition)")).//
andExpect(jsonPath("$._embedded.books[1].title").value("Spring Data")).//
andExpect(client.hasLinkWithRel("self"));
client.follow(findByLink.expand("0", "10", "unknown,asc,sales,asc")).//
andExpect(jsonPath("$._embedded.books[0].title").value("Spring Data")).//
andExpect(jsonPath("$._embedded.books[1].title").value("Spring Data (Second Edition)")).//
andExpect(client.hasLinkWithRel("self"));
}
/**
* @see DATAREST-160
*/

View File

@@ -53,8 +53,8 @@ public class TestDataPopulator {
Iterable<Author> authors = this.authors.save(Arrays.asList(ollie, mark, michael, david, john, thomas));
books.save(new Book("1449323952", "Spring Data", authors));
books.save(new Book("1449323953", "Spring Data (Second Edition)", authors));
books.save(new Book("1449323952", "Spring Data", 1000, authors));
books.save(new Book("1449323953", "Spring Data (Second Edition)", 2000, authors));
}
private void populateOrders() {