在 Spring 数据 JPA 中使用 Closed Projection 失败,出现 MappingException
Using Closed Projection in Spring Data JPA failed with MappingException
我尝试通过使用 interface-based Projection in Spring Data JPA 从 JPA 实体 Data
获取属性的子集,以最小化来自我的前端的 HTTP 请求的 JSON 响应数据(Angular).
使用 Closed Projection 似乎是处理该问题的好方法 - 易于实施且易于维护。
public interface DataRepository extends JpaRepository<Data, Long> {
List<DataView> findByLocation(String location))
interface DataView {
String getLocation();
}
}
我正在使用 JpaRepository
来获得 Spring 数据存储库功能的完整范围,但我在 Tomcat 控制台中收到以下异常:
org.springframework.data.mapping.MappingException: Couldn't find PersistentEntity for type class com.sun.proxy.$Proxy121!
at org.springframework.data.mapping.context.MappingContext.getRequiredPersistentEntity(MappingContext.java:79) ~[spring-data-commons-2.5.2.jar:2.5.2]
at org.springframework.data.mapping.context.PersistentEntities.getRequiredPersistentEntity(PersistentEntities.java:115) ~[spring-data-commons-2.5.2.jar:2.5.2]
at org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler.wrap(PersistentEntityResourceAssembler.java:90) ~[spring-data-rest-webmvc-3.5.2.jar:3.5.2]
at org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler.toModel(PersistentEntityResourceAssembler.java:73) ~[spring-data-rest-webmvc-3.5.2.jar:3.5.2]
at org.springframework.data.rest.webmvc.AbstractRepositoryRestController.entitiesToResources(AbstractRepositoryRestController.java:110) ~[spring-data-rest-webmvc-3.5.2.jar:3.5.2]
at org.springframework.data.rest.webmvc.AbstractRepositoryRestController.toCollectionModel(AbstractRepositoryRestController.java:80) ~[spring-data-rest-webmvc-3.5.2.jar:3.5.2]
at org.springframework.data.rest.webmvc.RepositorySearchController.lambda$toModel(RepositorySearchController.java:204) ~[spring-data-rest-webmvc-3.5.2.jar:3.5.2]
at java.base/java.util.Optional.map(Optional.java:258) ~[na:na]
at org.springframework.data.rest.webmvc.RepositorySearchController.toModel(RepositorySearchController.java:201) ~[spring-data-rest-webmvc-3.5.2.jar:3.5.2]
at org.springframework.data.rest.webmvc.RepositorySearchController.executeSearch(RepositorySearchController.java:185) ~[spring-data-rest-webmvc-3.5.2.jar:3.5.2]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.8.jar:5.3.8]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.8.jar:5.3.8]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.8.jar:5.3.8]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894) ~[spring-webmvc-5.3.8.jar:5.3.8]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.8.jar:5.3.8]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.8.jar:5.3.8]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1063) ~[spring-webmvc-5.3.8.jar:5.3.8]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.8.jar:5.3.8]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.8.jar:5.3.8]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.8.jar:5.3.8]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[servlet-api.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.8.jar:5.3.8]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[servlet-api.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[catalina.jar:9.0.56]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-websocket.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[catalina.jar:9.0.56]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.8.jar:5.3.8]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar:5.3.8]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[catalina.jar:9.0.56]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.8.jar:5.3.8]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar:5.3.8]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[catalina.jar:9.0.56]
at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:126) ~[spring-boot-2.5.2.jar:2.5.2]
at org.springframework.boot.web.servlet.support.ErrorPageFilter.access[=12=]0(ErrorPageFilter.java:64) ~[spring-boot-2.5.2.jar:2.5.2]
at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilterInternal(ErrorPageFilter.java:101) ~[spring-boot-2.5.2.jar:2.5.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar:5.3.8]
at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:119) ~[spring-boot-2.5.2.jar:2.5.2]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[catalina.jar:9.0.56]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.8.jar:5.3.8]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar:5.3.8]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[catalina.jar:9.0.56]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[catalina.jar:9.0.56]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[catalina.jar:9.0.56]
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[catalina.jar:9.0.56]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[catalina.jar:9.0.56]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) ~[tomcat-coyote.jar:9.0.56]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-coyote.jar:9.0.56]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895) ~[tomcat-coyote.jar:9.0.56]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732) ~[tomcat-coyote.jar:9.0.56]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-coyote.jar:9.0.56]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-util.jar:9.0.56]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-util.jar:9.0.56]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-util.jar:9.0.56]
at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na]
I read that“在幕后,Spring为每个实体对象创建一个投影接口的代理实例,所有对代理的调用都转发到该对象。”
我做错了什么?
如果您需要更多信息,请告诉我。
在此先感谢您的帮助!
编辑
我注意到如果前端请求 URL,我会收到 CORS 错误 'Access-Control-Allow-Origin'。我假设响应是某种交叉来源。这是我之前指出的代理实例造成的吗?那将是一个非常奇怪的行为。我将尝试将 cors.allowed.headers
添加到开发 tomcat 实例并检查它。
应用 CORS 过滤器的结果
如果我将 http://localhost:8080
或 http://localhost:4200
添加到 dev pr prod tomcat 实例 web.xml
,则会出现与以前相同的错误。我认为,代理实例指的是另一个 URL。有人有想法吗?
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>http://localhost:4200,http://localhost:8080</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Access-Control-Allow-Origin</param-value>
</init-param>
<init-param>
<param-name>cors.exposed.headers</param-name>
<param-value>Access-Control-Allow-Origin</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
class Data
必须是 JPA 实体。我怀疑 Data 只是一个普通的 DTO class。实体Data
的ID是Long
类型,参数Integer
用于查询实体。 @RequestParam
在控制器中使用,这里不需要。 findById
已经存在于 CRUD
仓库中,不建议覆盖它。最好使用另一个方法名称。存储库名称是 SensorDataRepository
,这意味着它是用来管理实体 SensorData
而不是实体 Data
.
存储库和投影界面应如下所示。
public interface DataRepository extends JpaRepository<Data, Long> {
List<DataView> findDataViewById(Long id);
interface DataView {
Long getId(); // if the field name is `id`, the method name should be `getId()`
}
}
如果spring-data-rest projection没问题
而不是 JPA 投影
尝试
将 DataView
接口 class 移动到 Data
实体所在的同一包中
并在 DataView
class 之上添加以下注释
@Projection(name = "dataView", types = Data.class)
然后将 ?projection=dataView
查询参数添加到您的搜索 url
例如:
http://localhost:8080/data/search/findByLocation?location=someplace&projection=dataView
我想出了一种新方法来找到一种解决方案,以最大限度地减少 HTTP 请求的 JSON 响应数据。关键词是Cache requests。它没有解决我提出的问题,但解决了我遇到的一般问题。
现在,我没有在我的网络应用程序中缓存任何内容。因此,对于导致 HTTP 请求的每次导航更改,它都会向后端请求数据。有点不良行为。
这应该是一个很好的解决方案,可以避免 95% 的网络流量。当我重新考虑我以前只响应实体的属性子集的方法时,这真是太愚蠢了……:)
终于明白自己做错了什么了...
直到昨天,我才处理 GET 请求,仅使用 Springs @Repository
和 @SpringBootApplication
就可以很好地工作。今天,我开始处理 POST 请求,这需要对请求进行不同的映射。 Springs @RestController
可以处理。在 tutorial 中,控制器 returns 一个 class ResponseEntity<T>
通过使用完整的 Spring MVC 方法实际处理请求的响应、不同的媒体类型等。
关闭的投影和所有 DTO 对应的东西现在工作得很好。
尽管如此,感谢大家的宝贵时间 - 尤其是@indybee!
我尝试通过使用 interface-based Projection in Spring Data JPA 从 JPA 实体 Data
获取属性的子集,以最小化来自我的前端的 HTTP 请求的 JSON 响应数据(Angular).
使用 Closed Projection 似乎是处理该问题的好方法 - 易于实施且易于维护。
public interface DataRepository extends JpaRepository<Data, Long> {
List<DataView> findByLocation(String location))
interface DataView {
String getLocation();
}
}
我正在使用 JpaRepository
来获得 Spring 数据存储库功能的完整范围,但我在 Tomcat 控制台中收到以下异常:
org.springframework.data.mapping.MappingException: Couldn't find PersistentEntity for type class com.sun.proxy.$Proxy121!
at org.springframework.data.mapping.context.MappingContext.getRequiredPersistentEntity(MappingContext.java:79) ~[spring-data-commons-2.5.2.jar:2.5.2]
at org.springframework.data.mapping.context.PersistentEntities.getRequiredPersistentEntity(PersistentEntities.java:115) ~[spring-data-commons-2.5.2.jar:2.5.2]
at org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler.wrap(PersistentEntityResourceAssembler.java:90) ~[spring-data-rest-webmvc-3.5.2.jar:3.5.2]
at org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler.toModel(PersistentEntityResourceAssembler.java:73) ~[spring-data-rest-webmvc-3.5.2.jar:3.5.2]
at org.springframework.data.rest.webmvc.AbstractRepositoryRestController.entitiesToResources(AbstractRepositoryRestController.java:110) ~[spring-data-rest-webmvc-3.5.2.jar:3.5.2]
at org.springframework.data.rest.webmvc.AbstractRepositoryRestController.toCollectionModel(AbstractRepositoryRestController.java:80) ~[spring-data-rest-webmvc-3.5.2.jar:3.5.2]
at org.springframework.data.rest.webmvc.RepositorySearchController.lambda$toModel(RepositorySearchController.java:204) ~[spring-data-rest-webmvc-3.5.2.jar:3.5.2]
at java.base/java.util.Optional.map(Optional.java:258) ~[na:na]
at org.springframework.data.rest.webmvc.RepositorySearchController.toModel(RepositorySearchController.java:201) ~[spring-data-rest-webmvc-3.5.2.jar:3.5.2]
at org.springframework.data.rest.webmvc.RepositorySearchController.executeSearch(RepositorySearchController.java:185) ~[spring-data-rest-webmvc-3.5.2.jar:3.5.2]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.8.jar:5.3.8]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.8.jar:5.3.8]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.8.jar:5.3.8]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894) ~[spring-webmvc-5.3.8.jar:5.3.8]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.8.jar:5.3.8]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.8.jar:5.3.8]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1063) ~[spring-webmvc-5.3.8.jar:5.3.8]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.8.jar:5.3.8]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.8.jar:5.3.8]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.8.jar:5.3.8]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[servlet-api.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.8.jar:5.3.8]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[servlet-api.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[catalina.jar:9.0.56]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-websocket.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[catalina.jar:9.0.56]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.8.jar:5.3.8]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar:5.3.8]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[catalina.jar:9.0.56]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.8.jar:5.3.8]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar:5.3.8]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[catalina.jar:9.0.56]
at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:126) ~[spring-boot-2.5.2.jar:2.5.2]
at org.springframework.boot.web.servlet.support.ErrorPageFilter.access[=12=]0(ErrorPageFilter.java:64) ~[spring-boot-2.5.2.jar:2.5.2]
at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilterInternal(ErrorPageFilter.java:101) ~[spring-boot-2.5.2.jar:2.5.2]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar:5.3.8]
at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:119) ~[spring-boot-2.5.2.jar:2.5.2]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[catalina.jar:9.0.56]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.8.jar:5.3.8]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar:5.3.8]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[catalina.jar:9.0.56]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[catalina.jar:9.0.56]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[catalina.jar:9.0.56]
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687) ~[catalina.jar:9.0.56]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[catalina.jar:9.0.56]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[catalina.jar:9.0.56]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) ~[tomcat-coyote.jar:9.0.56]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-coyote.jar:9.0.56]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895) ~[tomcat-coyote.jar:9.0.56]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732) ~[tomcat-coyote.jar:9.0.56]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-coyote.jar:9.0.56]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-util.jar:9.0.56]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-util.jar:9.0.56]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-util.jar:9.0.56]
at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na]
I read that“在幕后,Spring为每个实体对象创建一个投影接口的代理实例,所有对代理的调用都转发到该对象。”
我做错了什么?
如果您需要更多信息,请告诉我。
在此先感谢您的帮助!
编辑
我注意到如果前端请求 URL,我会收到 CORS 错误 'Access-Control-Allow-Origin'。我假设响应是某种交叉来源。这是我之前指出的代理实例造成的吗?那将是一个非常奇怪的行为。我将尝试将 cors.allowed.headers
添加到开发 tomcat 实例并检查它。
应用 CORS 过滤器的结果
如果我将 http://localhost:8080
或 http://localhost:4200
添加到 dev pr prod tomcat 实例 web.xml
,则会出现与以前相同的错误。我认为,代理实例指的是另一个 URL。有人有想法吗?
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>http://localhost:4200,http://localhost:8080</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Access-Control-Allow-Origin</param-value>
</init-param>
<init-param>
<param-name>cors.exposed.headers</param-name>
<param-value>Access-Control-Allow-Origin</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
class Data
必须是 JPA 实体。我怀疑 Data 只是一个普通的 DTO class。实体Data
的ID是Long
类型,参数Integer
用于查询实体。 @RequestParam
在控制器中使用,这里不需要。 findById
已经存在于 CRUD
仓库中,不建议覆盖它。最好使用另一个方法名称。存储库名称是 SensorDataRepository
,这意味着它是用来管理实体 SensorData
而不是实体 Data
.
存储库和投影界面应如下所示。
public interface DataRepository extends JpaRepository<Data, Long> {
List<DataView> findDataViewById(Long id);
interface DataView {
Long getId(); // if the field name is `id`, the method name should be `getId()`
}
}
如果spring-data-rest projection没问题 而不是 JPA 投影
尝试
将
DataView
接口 class 移动到Data
实体所在的同一包中并在
DataView
class 之上添加以下注释@Projection(name = "dataView", types = Data.class)
然后将
?projection=dataView
查询参数添加到您的搜索 url
例如:
http://localhost:8080/data/search/findByLocation?location=someplace&projection=dataView
我想出了一种新方法来找到一种解决方案,以最大限度地减少 HTTP 请求的 JSON 响应数据。关键词是Cache requests。它没有解决我提出的问题,但解决了我遇到的一般问题。
现在,我没有在我的网络应用程序中缓存任何内容。因此,对于导致 HTTP 请求的每次导航更改,它都会向后端请求数据。有点不良行为。
这应该是一个很好的解决方案,可以避免 95% 的网络流量。当我重新考虑我以前只响应实体的属性子集的方法时,这真是太愚蠢了……:)
终于明白自己做错了什么了...
直到昨天,我才处理 GET 请求,仅使用 Springs @Repository
和 @SpringBootApplication
就可以很好地工作。今天,我开始处理 POST 请求,这需要对请求进行不同的映射。 Springs @RestController
可以处理。在 tutorial 中,控制器 returns 一个 class ResponseEntity<T>
通过使用完整的 Spring MVC 方法实际处理请求的响应、不同的媒体类型等。
关闭的投影和所有 DTO 对应的东西现在工作得很好。
尽管如此,感谢大家的宝贵时间 - 尤其是@indybee!