DATAREST-502 - Prepare request parameters to enable URI-to-entity resolution for executing searches.
RepositorySearchController now takes all request parameters as MultiValueMap to execute query methods. For parameters mapping to a managed resource we try to interpret the given parameter value as URI to actually trigger the URI-to-entity resolution through the newly registered UriToEntityConverter. The latter is now registered with the default ConversionService registered so that it's A lot of cleanups in RepositorySearchController. Removed some obsolete prints to the console to reduce log output during test execution. Related ticket: DATACMNS-678.
This commit is contained in:
@@ -81,7 +81,7 @@ public class UriToEntityConverter implements ConditionalGenericConverter {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||||
return conversionService.canConvert(STRING_TYPE, targetType);
|
return !sourceType.equals(URI_TYPE) ? false : conversionService.canConvert(STRING_TYPE, targetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -18,16 +18,21 @@ package org.springframework.data.rest.webmvc;
|
|||||||
import static org.springframework.data.rest.webmvc.ControllerUtils.*;
|
import static org.springframework.data.rest.webmvc.ControllerUtils.*;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.core.MethodParameter;
|
||||||
import org.springframework.data.auditing.AuditableBeanWrapperFactory;
|
import org.springframework.data.auditing.AuditableBeanWrapperFactory;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
import org.springframework.data.repository.support.RepositoryInvoker;
|
import org.springframework.data.repository.support.RepositoryInvoker;
|
||||||
import org.springframework.data.rest.core.mapping.ResourceMappings;
|
import org.springframework.data.rest.core.mapping.ResourceMappings;
|
||||||
|
import org.springframework.data.rest.core.mapping.ResourceMetadata;
|
||||||
import org.springframework.data.rest.core.mapping.SearchResourceMappings;
|
import org.springframework.data.rest.core.mapping.SearchResourceMappings;
|
||||||
import org.springframework.data.rest.webmvc.support.DefaultedPageable;
|
import org.springframework.data.rest.webmvc.support.DefaultedPageable;
|
||||||
import org.springframework.data.rest.webmvc.support.RepositoryEntityLinks;
|
import org.springframework.data.rest.webmvc.support.RepositoryEntityLinks;
|
||||||
@@ -39,17 +44,21 @@ import org.springframework.hateoas.Links;
|
|||||||
import org.springframework.hateoas.Resource;
|
import org.springframework.hateoas.Resource;
|
||||||
import org.springframework.hateoas.ResourceSupport;
|
import org.springframework.hateoas.ResourceSupport;
|
||||||
import org.springframework.hateoas.Resources;
|
import org.springframework.hateoas.Resources;
|
||||||
|
import org.springframework.hateoas.core.AnnotationAttribute;
|
||||||
|
import org.springframework.hateoas.core.MethodParameters;
|
||||||
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpEntity;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import org.springframework.web.context.request.WebRequest;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller to lookup and execute searches on a given repository.
|
* Controller to lookup and execute searches on a given repository.
|
||||||
@@ -153,20 +162,23 @@ class RepositorySearchController extends AbstractRepositoryRestController {
|
|||||||
/**
|
/**
|
||||||
* Executes the search with the given name.
|
* Executes the search with the given name.
|
||||||
*
|
*
|
||||||
* @param request
|
* @param resourceInformation
|
||||||
* @param repository
|
* @param parameters
|
||||||
* @param search
|
* @param search
|
||||||
* @param pageable
|
* @param pageable
|
||||||
|
* @param sort
|
||||||
|
* @param assembler
|
||||||
* @return
|
* @return
|
||||||
* @throws ResourceNotFoundException
|
* @throws ResourceNotFoundException
|
||||||
*/
|
*/
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@RequestMapping(value = BASE_MAPPING + "/{search}", method = RequestMethod.GET)
|
@RequestMapping(value = BASE_MAPPING + "/{search}", method = RequestMethod.GET)
|
||||||
public ResponseEntity<Object> executeSearch(RootResourceInformation resourceInformation, WebRequest request,
|
public ResponseEntity<Object> executeSearch(RootResourceInformation resourceInformation,
|
||||||
@PathVariable String search, DefaultedPageable pageable, Sort sort, PersistentEntityResourceAssembler assembler) {
|
@RequestParam MultiValueMap<String, Object> parameters, @PathVariable String search, DefaultedPageable pageable,
|
||||||
|
Sort sort, PersistentEntityResourceAssembler assembler) {
|
||||||
|
|
||||||
Method method = checkExecutability(resourceInformation, search);
|
Method method = checkExecutability(resourceInformation, search);
|
||||||
Object result = executeQueryMethod(resourceInformation.getInvoker(), request, method, pageable, sort, assembler);
|
Object result = executeQueryMethod(resourceInformation.getInvoker(), parameters, method, pageable, sort, assembler);
|
||||||
|
|
||||||
return new ResponseEntity<Object>(toResource(result, assembler, null), HttpStatus.OK);
|
return new ResponseEntity<Object>(toResource(result, assembler, null), HttpStatus.OK);
|
||||||
}
|
}
|
||||||
@@ -175,20 +187,23 @@ class RepositorySearchController extends AbstractRepositoryRestController {
|
|||||||
* Executes a query method and exposes the results in compact form.
|
* Executes a query method and exposes the results in compact form.
|
||||||
*
|
*
|
||||||
* @param resourceInformation
|
* @param resourceInformation
|
||||||
|
* @param parameters
|
||||||
* @param repository
|
* @param repository
|
||||||
* @param method
|
* @param searcg
|
||||||
* @param pageable
|
* @param pageable
|
||||||
|
* @param sort
|
||||||
|
* @param assembler
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@RequestMapping(value = BASE_MAPPING + "/{search}", method = RequestMethod.GET, //
|
@RequestMapping(value = BASE_MAPPING + "/{search}", method = RequestMethod.GET, //
|
||||||
produces = { "application/x-spring-data-compact+json" })
|
produces = { "application/x-spring-data-compact+json" })
|
||||||
public ResourceSupport executeSearchCompact(RootResourceInformation resourceInformation, WebRequest request,
|
public ResourceSupport executeSearchCompact(RootResourceInformation resourceInformation,
|
||||||
@PathVariable String repository, @PathVariable String search, DefaultedPageable pageable, Sort sort,
|
@RequestParam MultiValueMap<String, Object> parameters, @PathVariable String repository,
|
||||||
PersistentEntityResourceAssembler assembler) {
|
@PathVariable String search, DefaultedPageable pageable, Sort sort, PersistentEntityResourceAssembler assembler) {
|
||||||
|
|
||||||
Method method = checkExecutability(resourceInformation, search);
|
Method method = checkExecutability(resourceInformation, search);
|
||||||
Object result = executeQueryMethod(resourceInformation.getInvoker(), request, method, pageable, sort, assembler);
|
Object result = executeQueryMethod(resourceInformation.getInvoker(), parameters, method, pageable, sort, assembler);
|
||||||
Object resource = toResource(result, assembler, null);
|
Object resource = toResource(result, assembler, null);
|
||||||
List<Link> links = new ArrayList<Link>();
|
List<Link> links = new ArrayList<Link>();
|
||||||
|
|
||||||
@@ -272,11 +287,29 @@ class RepositorySearchController extends AbstractRepositoryRestController {
|
|||||||
* @param pageable
|
* @param pageable
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private Object executeQueryMethod(final RepositoryInvoker invoker, WebRequest request, Method method,
|
private Object executeQueryMethod(final RepositoryInvoker invoker,
|
||||||
DefaultedPageable pageable, Sort sort, PersistentEntityResourceAssembler assembler) {
|
@RequestParam MultiValueMap<String, Object> parameters, Method method, DefaultedPageable pageable, Sort sort,
|
||||||
|
PersistentEntityResourceAssembler assembler) {
|
||||||
|
|
||||||
Map<String, String[]> parameters = request.getParameterMap();
|
MultiValueMap<String, Object> result = new LinkedMultiValueMap<String, Object>(parameters);
|
||||||
return invoker.invokeQueryMethod(method, parameters, pageable.getPageable(), sort);
|
MethodParameters methodParameters = new MethodParameters(method, new AnnotationAttribute(Param.class));
|
||||||
|
|
||||||
|
for (Entry<String, List<Object>> entry : parameters.entrySet()) {
|
||||||
|
|
||||||
|
MethodParameter parameter = methodParameters.getParameter(entry.getKey());
|
||||||
|
|
||||||
|
if (parameter == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceMetadata metadata = mappings.getMappingFor(parameter.getParameterType());
|
||||||
|
|
||||||
|
if (metadata != null && metadata.isExported()) {
|
||||||
|
result.put(parameter.getParameterName(), prepareUris(entry.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return invoker.invokeQueryMethod(method, result, pageable.getPageable(), sort);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -284,7 +317,7 @@ class RepositorySearchController extends AbstractRepositoryRestController {
|
|||||||
*
|
*
|
||||||
* @param resourceInformation
|
* @param resourceInformation
|
||||||
*/
|
*/
|
||||||
private SearchResourceMappings verifySearchesExposed(RootResourceInformation resourceInformation) {
|
private static SearchResourceMappings verifySearchesExposed(RootResourceInformation resourceInformation) {
|
||||||
|
|
||||||
SearchResourceMappings resourceMappings = resourceInformation.getSearchMappings();
|
SearchResourceMappings resourceMappings = resourceInformation.getSearchMappings();
|
||||||
|
|
||||||
@@ -294,4 +327,31 @@ class RepositorySearchController extends AbstractRepositoryRestController {
|
|||||||
|
|
||||||
return resourceMappings;
|
return resourceMappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to turn all elements of the given {@link List} into URIs and falls back to keeping the original element if
|
||||||
|
* the conversion fails.
|
||||||
|
*
|
||||||
|
* @param source can be {@literal null}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static List<Object> prepareUris(List<Object> source) {
|
||||||
|
|
||||||
|
if (source == null || source.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Object> result = new ArrayList<Object>(source.size());
|
||||||
|
|
||||||
|
for (Object element : source) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
result.add(new URI(element.toString()));
|
||||||
|
} catch (URISyntaxException o_O) {
|
||||||
|
result.add(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import org.springframework.context.support.MessageSourceAccessor;
|
|||||||
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||||
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.data.auditing.AuditableBeanWrapperFactory;
|
import org.springframework.data.auditing.AuditableBeanWrapperFactory;
|
||||||
@@ -181,8 +182,8 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon
|
|||||||
public DefaultFormattingConversionService defaultConversionService() {
|
public DefaultFormattingConversionService defaultConversionService() {
|
||||||
|
|
||||||
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
|
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
|
||||||
|
|
||||||
// Add Spring Data Commons formatters
|
// Add Spring Data Commons formatters
|
||||||
|
conversionService.addConverter(uriToEntityConverter(conversionService));
|
||||||
addFormatters(conversionService);
|
addFormatters(conversionService);
|
||||||
|
|
||||||
configureConversionService(conversionService);
|
configureConversionService(conversionService);
|
||||||
@@ -540,8 +541,16 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon
|
|||||||
|
|
||||||
PersistentEntities entities = persistentEntities();
|
PersistentEntities entities = persistentEntities();
|
||||||
|
|
||||||
return new PersistentEntityJackson2Module(resourceMappings(), entities, config(), new UriToEntityConverter(
|
return new PersistentEntityJackson2Module(resourceMappings(), entities, config(),
|
||||||
entities, defaultConversionService()));
|
uriToEntityConverter(defaultConversionService()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param entities
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected UriToEntityConverter uriToEntityConverter(ConversionService conversionService) {
|
||||||
|
return new UriToEntityConverter(persistentEntities(), conversionService);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import org.springframework.data.rest.core.mapping.ResourceMetadata;
|
|||||||
import org.springframework.data.rest.webmvc.ResourceTester.HasSelfLink;
|
import org.springframework.data.rest.webmvc.ResourceTester.HasSelfLink;
|
||||||
import org.springframework.data.rest.webmvc.jpa.Address;
|
import org.springframework.data.rest.webmvc.jpa.Address;
|
||||||
import org.springframework.data.rest.webmvc.jpa.Author;
|
import org.springframework.data.rest.webmvc.jpa.Author;
|
||||||
|
import org.springframework.data.rest.webmvc.jpa.Book;
|
||||||
import org.springframework.data.rest.webmvc.jpa.CreditCard;
|
import org.springframework.data.rest.webmvc.jpa.CreditCard;
|
||||||
import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
|
import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
|
||||||
import org.springframework.data.rest.webmvc.jpa.Person;
|
import org.springframework.data.rest.webmvc.jpa.Person;
|
||||||
@@ -34,11 +35,14 @@ import org.springframework.data.rest.webmvc.jpa.TestDataPopulator;
|
|||||||
import org.springframework.data.rest.webmvc.support.DefaultedPageable;
|
import org.springframework.data.rest.webmvc.support.DefaultedPageable;
|
||||||
import org.springframework.hateoas.PagedResources;
|
import org.springframework.hateoas.PagedResources;
|
||||||
import org.springframework.hateoas.ResourceSupport;
|
import org.springframework.hateoas.ResourceSupport;
|
||||||
|
import org.springframework.hateoas.Resources;
|
||||||
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpEntity;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration tests for the {@link RepositorySearchController}.
|
* Integration tests for the {@link RepositorySearchController}.
|
||||||
@@ -49,6 +53,8 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@Transactional
|
@Transactional
|
||||||
public class RepositorySearchControllerIntegrationTests extends AbstractControllerIntegrationTests {
|
public class RepositorySearchControllerIntegrationTests extends AbstractControllerIntegrationTests {
|
||||||
|
|
||||||
|
static final DefaultedPageable PAGEABLE = new DefaultedPageable(new PageRequest(0, 10), true);
|
||||||
|
|
||||||
@Autowired TestDataPopulator loader;
|
@Autowired TestDataPopulator loader;
|
||||||
@Autowired RepositorySearchController controller;
|
@Autowired RepositorySearchController controller;
|
||||||
@Autowired PersistentEntityResourceAssembler assembler;
|
@Autowired PersistentEntityResourceAssembler assembler;
|
||||||
@@ -88,11 +94,12 @@ public class RepositorySearchControllerIntegrationTests extends AbstractControll
|
|||||||
@Test
|
@Test
|
||||||
public void executesSearchAgainstRepository() {
|
public void executesSearchAgainstRepository() {
|
||||||
|
|
||||||
RequestParameters parameters = new RequestParameters("firstname", "John");
|
|
||||||
RootResourceInformation resourceInformation = getResourceInformation(Person.class);
|
RootResourceInformation resourceInformation = getResourceInformation(Person.class);
|
||||||
|
MultiValueMap<String, Object> parameters = new LinkedMultiValueMap<String, Object>(1);
|
||||||
|
parameters.add("firstname", "John");
|
||||||
|
|
||||||
ResponseEntity<Object> response = controller.executeSearch(resourceInformation, getRequest(parameters),
|
ResponseEntity<Object> response = controller.executeSearch(resourceInformation, parameters, "firstname", PAGEABLE,
|
||||||
"firstname", new DefaultedPageable(new PageRequest(0, 10), true), null, assembler);
|
null, assembler);
|
||||||
|
|
||||||
ResourceTester tester = ResourceTester.of(response.getBody());
|
ResourceTester tester = ResourceTester.of(response.getBody());
|
||||||
PagedResources<Object> pagedResources = tester.assertIsPage();
|
PagedResources<Object> pagedResources = tester.assertIsPage();
|
||||||
@@ -169,4 +176,21 @@ public class RepositorySearchControllerIntegrationTests extends AbstractControll
|
|||||||
|
|
||||||
assertAllowHeaders(response, HttpMethod.GET);
|
assertAllowHeaders(response, HttpMethod.GET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see DATAREST-502
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void interpretsUriAsReferenceToRelatedEntity() {
|
||||||
|
|
||||||
|
MultiValueMap<String, Object> parameters = new LinkedMultiValueMap<String, Object>(1);
|
||||||
|
parameters.add("author", "/author/1");
|
||||||
|
|
||||||
|
RootResourceInformation resourceInformation = getResourceInformation(Book.class);
|
||||||
|
|
||||||
|
ResponseEntity<Object> result = controller.executeSearch(resourceInformation, parameters, "findByAuthorsContains",
|
||||||
|
PAGEABLE, null, assembler);
|
||||||
|
|
||||||
|
assertThat(result.getBody(), is(instanceOf(Resources.class)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import org.springframework.mock.web.MockHttpServletResponse;
|
|||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.web.WebAppConfiguration;
|
import org.springframework.test.context.web.WebAppConfiguration;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
|
|
||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
|
||||||
@@ -138,8 +137,8 @@ public class AlpsControllerIntegrationTests extends AbstractControllerIntegratio
|
|||||||
|
|
||||||
assertThat(usersLink, is(notNullValue()));
|
assertThat(usersLink, is(notNullValue()));
|
||||||
|
|
||||||
mvc.perform(get(usersLink.getHref())).andDo(MockMvcResultHandlers.print())
|
mvc.perform(get(usersLink.getHref())).//
|
||||||
.andExpect(jsonPath("$.descriptors[?(@.id == 'item-representation')].href", is(notNullValue())));
|
andExpect(jsonPath("$.descriptors[?(@.id == 'item-representation')].href", is(notNullValue())));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Link discoverUnique(String href, String rel) throws Exception {
|
private Link discoverUnique(String href, String rel) throws Exception {
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ package org.springframework.data.rest.webmvc.jpa;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.CrudRepository;
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
|
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
|
||||||
import org.springframework.data.rest.core.annotation.RestResource;
|
import org.springframework.data.rest.core.annotation.RestResource;
|
||||||
|
|
||||||
@@ -30,4 +32,7 @@ public interface BookRepository extends CrudRepository<Book, Long> {
|
|||||||
|
|
||||||
@RestResource(rel = "find-by-sorted")
|
@RestResource(rel = "find-by-sorted")
|
||||||
List<Book> findBy(Sort sort);
|
List<Book> findBy(Sort sort);
|
||||||
|
|
||||||
|
@Query("select b from Book b where :author member of b.authors")
|
||||||
|
List<Book> findByAuthorsContains(@Param("author") Author author);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,8 +132,6 @@ public class PersistentEntityToJsonSchemaConverterUnitTests {
|
|||||||
|
|
||||||
String writeSchemaFor = writeSchemaFor(type);
|
String writeSchemaFor = writeSchemaFor(type);
|
||||||
|
|
||||||
System.out.println(writeSchemaFor);
|
|
||||||
|
|
||||||
for (Constraint constraint : constraints) {
|
for (Constraint constraint : constraints) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user