【问题标题】:Spring Data Rest: "Unable to configure LocalContainerEntityManagerFactoryBean from @EntityScan"Spring Data Rest:“无法从 @EntityScan 配置 LocalContainerEntityManagerFactoryBean”
【发布时间】:2025-12-27 21:05:07
【问题描述】:

我有一个 REST 服务 spring boot 应用程序,由两个独立的 maven 项目组成:

  1. 第一个 myapp-data 包括 Spring Data JPA + Spring Data Rest Entities 和 Rest Repositories 类定义(我已将它们隔离在一个单独的 maven 项目中,因为除了我的 REST 服务之外,我还在其他应用程序中使用它们)。李>
  2. 第二个 myapp-services 是一个 Spring Boot 应用程序,它基本上包含 main 方法 + 配置,以将上述 Spring Data Rest 存储库公开为 REST 端点。

如果我在本地开发环境中运行它(STS Eclipse,在我的本地开发机器上启动 mvn spring-boot:run),一切似乎都运行良好,但是当我将它部署为一个暂存 tomcat 环境(ubuntu 14.04 下的 tomcat7)时) 我在下面的框中得到了例外。请注意,除此之外,两个部署的区别仅在于application.properties 中的不同设置(数据库连接、日志记录级别等)。

在我进行一些代码更改之前(例如,在以前的版本中,我使用了普通的 JPA 存储库和自定义 Rest 控制器而不是 Spring Data Rest 存储库),应用程序在开发和暂存环境中都部署得很好。当我添加 Spring Data Rest 存储库时,问题可能开始出现,但我不是 100% 确定这一点,因为我在连续进行了一些其他小的更改后部署在暂存环境中。

这是异常堆栈跟踪:

java.lang.IllegalStateException: Unable to configure LocalContainerEntityManagerFactoryBean from @EntityScan, ensure an appropriate bean is registered.
        at org.springframework.util.Assert.state(Assert.java:392)
        at org.springframework.boot.orm.jpa.EntityScanRegistrar$EntityScanBeanPostProcessor.afterSingletonsInstantiated(EntityScanRegistrar.java:148)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:792)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766)
        at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
        at org.springframework.boot.context.web.SpringBootServletInitializer.run(SpringBootServletInitializer.java:149)
        at org.springframework.boot.context.web.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:129)
        at org.springframework.boot.context.web.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:85)
        at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:169)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5456)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.manager.ManagerServlet.start(ManagerServlet.java:1256)
        at org.apache.catalina.manager.HTMLManagerServlet.start(HTMLManagerServlet.java:692)
        at org.apache.catalina.manager.HTMLManagerServlet.doPost(HTMLManagerServlet.java:217)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.apache.catalina.filters.CsrfPreventionFilter.doFilter(CsrfPreventionFilter.java:213)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:610)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

这是myapp-services 项目的主要应用程序类:

package eu.myapp.services;

@ComponentScan(value="eu.myapp")
@EnableJpaRepositories("eu.myapp.data")
@EntityScan(value="eu.myapp.data")
@SpringBootApplication
public class MyappServicesApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(MyappServicesApplication.class, args);
    }
}

其中eu.myapp.data 是在myapp-data 项目中定义的包,作为maven 依赖项包含在内,包含实体和存储库类定义。

在我的服务项目配置中,我使用带有自定义 UserDetailsS​​ervice 的 Spring Security(不知道这是否相关,.. 它在以前的部署中有效,所以可能不是)。

【问题讨论】:

    标签: spring-boot tomcat7 spring-data-rest


    【解决方案1】:

    我不知道是否为时已晚,但我将告诉您我为解决此问题所做的工作以供将来参考。

    显然问题与 Spring Security 和自定义 UserDetailsS​​ervice 有关。

    我认为主应用程序类和你的SpringSecurity配置类一旦尝试同时访问数据库层就会发生冲突。

    要解决此问题,您可以将标签@Order(1) 添加到主类,并将另一个标签(例如@Order(30))添加到安全类。

    我不知道为什么只有将应用程序部署到网络服务器时才会发生这种情况(对我来说是 Glassfish 4.1.1)。

    希望对你有帮助。

    其他参考资料:

    https://github.com/spring-projects/spring-boot/issues/1008

    【讨论】:

    • 感谢您的建议(我现在才看到它,因为我过去几周正在度假)。最后,我决定将该服务也部署在生产环境中作为独立(嵌入式 tomcat)spring boot 应用程序,而不是安装在生产服务器的 tomcat 实例上。由于除了解决我的异常之外,这种方法还具有许多其他优点,我决定坚持这一点,并没有进一步调查这个问题。无论如何,由于我很想验证您的解决方案是否有效,所以一旦有时间,我会试一试并告诉您它是否有效。
    【解决方案2】:

    不确定这是否会帮助任何人,但...

    我也遇到了同样的问题,结果变成了一门课

    extends org.springframework.boot.context.web.SpringBootServletInitializer

    这是导致问题的原因。我能够重构代码并将其删除,从而消除了错误。

    希望有人觉得这很有用。

    【讨论】: