我有一个简单的Spring Boot应用程序,其中包含Spring Data JPA和Spring Data Rest模块。
Spring Data Rest会自动公开JPA Repositories,但是当我向存储库中的自定义搜索方法发送HTTP GET请求时,该方法返回一个投影列表,我会收到Couldn't find PersistentEntity for type class com.sun.proxy.$Proxy117!
的错误。当我将该方法的返回类型从投影列表更改为仅投影时,它就可以正常工作。
Person实体类
@Entity
public class Person {
@Id
@GeneratedValue
private Long id;
@Column
private String name;
@Column
private String surname;
}
人员仓库
public interface PersonRepository extends JpaRepository<Person, Long> {
List<NameProjection> findByNameContains(@Param(value = "name") String name);
}
投影
@Projection(name = "nameProjection", types = {Person.class})
public interface NameProjection {
String getName();
}
链接: http://localhost:8080/persons/search/findByNameContains?name=a
堆栈跟踪:
java.lang.IllegalArgumentException: Couldn't find PersistentEntity for type class com.sun.proxy.$Proxy117!
at org.springframework.data.mapping.context.PersistentEntities.lambda$getRequiredPersistentEntity$2(PersistentEntities.java:78) ~[spring-data-commons-2.0.6.RELEASE.jar:2.0.6.RELEASE]
at java.util.Optional.orElseThrow(Optional.java:290) ~[na:1.8.0_161]
at org.springframework.data.mapping.context.PersistentEntities.getRequiredPersistentEntity(PersistentEntities.java:77) ~[spring-data-commons-2.0.6.RELEASE.jar:2.0.6.RELEASE]
at org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler.wrap(PersistentEntityResourceAssembler.java:72) ~[spring-data-rest-webmvc-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler.toResource(PersistentEntityResourceAssembler.java:55) ~[spring-data-rest-webmvc-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.data.rest.webmvc.AbstractRepositoryRestController.entitiesToResources(AbstractRepositoryRestController.java:110) ~[spring-data-rest-webmvc-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.data.rest.webmvc.AbstractRepositoryRestController.toResources(AbstractRepositoryRestController.java:80) ~[spring-data-rest-webmvc-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.data.rest.webmvc.RepositorySearchController.lambda$toResource$1(RepositorySearchController.java:209) ~[spring-data-rest-webmvc-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at java.util.Optional.map(Optional.java:215) ~[na:1.8.0_161]
at org.springframework.data.rest.webmvc.RepositorySearchController.toResource(RepositorySearchController.java:206) ~[spring-data-rest-webmvc-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.data.rest.webmvc.RepositorySearchController.executeSearch(RepositorySearchController.java:190) ~[spring-data-rest-webmvc-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_161]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) ~[spring-webmvc-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877) ~[spring-webmvc-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783) ~[spring-webmvc-5.0.5.RELEASE.jar:5.0.5.RELEASE]
有一个示例项目在https://github.com/mahsumdemir/projection-demo,用于展示错误。启动项目后,转到http://localhost:8080/persons/search/findByNameContains?name=i网址,您将看到错误。
更新:
我想返回
List<NameProjection>
,因为Spring Data JPA使用存储库方法的返回类型来确定将在数据库上执行的SQL。调用返回类型为List<Person>
的方法会在数据库上执行select * from person;
。但是,调用返回类型为List<NameProjection>
的方法将在数据库上执行select name from person;
。从数据库中收集的额外数据在Person实体的情况下不是问题。但是,在操作具有多媒体列的实体时,这是一个大问题。更新2:
相关的jira问题:https://jira.spring.io/browse/DATAREST-1237。
List<NameProjection>
,因为Spring Data JPA使用存储库方法的返回类型来确定将在数据库上执行的SQL。调用返回类型为List<Person>
的方法会在数据库上执行select * from person;
。但是调用返回类型为List<NameProjection>
的方法会在数据库上执行select name from person;
。对于Person实体,从数据库中获取的额外数据不是问题。但是,在操作具有多媒体列的实体时,这是一个大问题。 - mahsumList<NameProjection>
executesselect name from person;
I don't think so, have a try with a @Restcontroler and set propertyspring.jpa.show-sql=true
- Dirk Deyne