首页 > 解决方案 > 用于 Spring 存储库的自定义 ResourceAssembler

问题描述

我使用 Spring Data REST、Spring HATEOAS、Hibernate 创建了一个 Spring Boot 2 应用程序。

我想创建一个自定义 ResourceAssembler。我完成了创建这个bean:

@Component
public class StringResourceAssembler implements ResourceAssembler<String, Resource<String>> {

    @Autowired
    private EntityLinks entityLinks;

    @Override
    public Resource<String> toResource(String question) {
        Resource<String> resource = new Resource<String>(question);
        return resource;
    }
}

我需要一个客户 ResourceAssembler 因为在 Spring Repository 我有这个方法:

@Transactional
@PreAuthorize("isAuthenticated()")
public interface FrameRepository extends JpaRepository<Frame, Long> {

     @Transactional(readOnly = true)
     @Query(value = "SELECT DISTINCT f.manufacturer FROM Frame f WHERE :searchString IS NULL OR (f.manufacturer LIKE CONCAT(:searchString,'%')) GROUP BY f.manufacturer ORDER BY f.manufacturer")
     public Page<String> manufacturerAutocomplete(@Param("searchString") String searchString, Pageable pageable);

如您所见,我的方法是由 Spring Data REST 导出的,它返回一页字符串值(我在枚举方面遇到了同样的问题)。

不幸的是我有这个例外:

15/11/2018 12:09:45,054 ERROR http-nio-8082-exec-7 RepositoryRestExceptionHandler:168 - Couldn't find PersistentEntity for type class java.lang.String!
java.lang.IllegalArgumentException: Couldn't find PersistentEntity for type class java.lang.String!
    at org.springframework.data.mapping.context.PersistentEntities.lambda$getRequiredPersistentEntity$2(PersistentEntities.java:78) ~[spring-data-commons-2.0.8.RELEASE.jar:2.0.8.RELEASE]
    at java.util.Optional.orElseThrow(Optional.java:290) ~[?:1.8.0_181]
    at org.springframework.data.mapping.context.PersistentEntities.getRequiredPersistentEntity(PersistentEntities.java:77) ~[spring-data-commons-2.0.8.RELEASE.jar:2.0.8.RELEASE]
    at org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler.wrap(PersistentEntityResourceAssembler.java:72) ~[spring-data-rest-webmvc-3.0.8.RELEASE.jar:3.0.8.RELEASE]
    at org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler.toResource(PersistentEntityResourceAssembler.java:55) ~[spring-data-rest-webmvc-3.0.8.RELEASE.jar:3.0.8.RELEASE]
    at org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler.toResource(PersistentEntityResourceAssembler.java:38) ~[spring-data-rest-webmvc-3.0.8.RELEASE.jar:3.0.8.RELEASE]
    at org.springframework.data.web.PagedResourcesAssembler.createResource(PagedResourcesAssembler.java:208) ~[spring-data-commons-2.0.8.RELEASE.jar:2.0.8.RELEASE]
    at org.springframework.data.web.PagedResourcesAssembler.toResource(PagedResourcesAssembler.java:120) ~[spring-data-commons-2.0.8.RELEASE.jar:2.0.8.RELEASE]
    at org.springframework.data.rest.webmvc.AbstractRepositoryRestController.lambda$entitiesToResources$3(AbstractRepositoryRestController.java:95) ~[spring-data-rest-webmvc-3.0.8.RELEASE.jar:3.0.8.RELEASE]
    at java.util.Optional.orElseGet(Optional.java:267) ~[?:1.8.0_181]
    at org.springframework.data.rest.webmvc.AbstractRepositoryRestController.entitiesToResources(AbstractRepositoryRestController.java:95) ~[spring-data-rest-webmvc-3.0.8.RELEASE.jar:3.0.8.RELEASE]
    at org.springframework.data.rest.webmvc.AbstractRepositoryRestController.toResources(AbstractRepositoryRestController.java:78) ~[spring-data-rest-webmvc-3.0.8.RELEASE.jar:3.0.8.RELEASE]
    at org.springframework.data.rest.webmvc.RepositorySearchController.lambda$toResource$1(RepositorySearchController.java:209) ~[spring-data-rest-webmvc-3.0.8.RELEASE.jar:3.0.8.RELEASE]
    at java.util.Optional.map(Optional.java:215) ~[?:1.8.0_181]
    at org.springframework.data.rest.webmvc.RepositorySearchController.toResource(RepositorySearchController.java:206) ~[spring-data-rest-webmvc-3.0.8.RELEASE.jar:3.0.8.RELEASE]
    at org.springframework.data.rest.webmvc.RepositorySearchController.executeSearch(RepositorySearchController.java:190) ~[spring-data-rest-webmvc-3.0.8.RELEASE.jar:3.0.8.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_181]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_181]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_181]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_181]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) ~[spring-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) ~[spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877) ~[spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783) ~[spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) [spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) [spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974) [spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866) [spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]

有没有办法让我的 ResourceAssembler 与 Spring Data REST 一起工作?

标签: javaspringspring-bootspring-data-rest

解决方案


创建一个要在其中保存结果的类。

    @AllArgsConstructor
    @NoArgsConstructor
    public class Result {
        private String manufacturer;
    }

存储方法:

@Transactional(readOnly = true)
@Query(value = "SELECT New Result(DISTINCT f.manufacturer) FROM Frame f WHERE :searchString IS NULL OR (f.manufacturer LIKE CONCAT(:searchString,'%')) GROUP BY f.manufacturer ORDER BY f.manufacturer")
public Page<Result> manufacturerAutocomplete(@Param("searchString") String searchString, Pageable pageable);

推荐阅读