【问题标题】:Spring boot - Not a managed typeSpring Boot - 不是托管类型
【发布时间】:2015-04-24 04:52:14
【问题描述】:

我用的是Spring boot+JPA,在启动服务的时候遇到了问题。

Caused by: java.lang.IllegalArgumentException: Not an managed type: class com.nervytech.dialer.domain.PhoneSettings
    at org.hibernate.jpa.internal.metamodel.MetamodelImpl.managedType(MetamodelImpl.java:219)
    at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:68)
    at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getMetadata(JpaEntityInformationSupport.java:65)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:145)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:89)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:69)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:177)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:239)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:225)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:92)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1625)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1562)

这是 Application.java 文件,

@Configuration
@ComponentScan
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })
@SpringBootApplication
public class DialerApplication {

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

我使用UCp做连接池,DataSource配置如下,

@Configuration
@ComponentScan
@EnableTransactionManagement
@EnableAutoConfiguration
@EnableJpaRepositories(entityManagerFactoryRef = "dialerEntityManagerFactory", transactionManagerRef = "dialerTransactionManager", basePackages = { "com.nervy.dialer.spring.jpa.repository" })
public class ApplicationDataSource {

    /** The Constant LOGGER. */
    private static final Logger LOGGER = LoggerFactory
            .getLogger(ApplicationDataSource.class);

    /** The Constant TEST_SQL. */
    private static final String TEST_SQL = "select 1 from dual";

    /** The pooled data source. */
    private PoolDataSource pooledDataSource;

UserDetailsS​​ervice 实现,

@Service("userDetailsService")
@SessionAttributes("user")
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserService userService;

服务层实现,

@Service
public class PhoneSettingsServiceImpl implements PhoneSettingsService {

}

存储库类,

@Repository
public interface PhoneSettingsRepository extends JpaRepository<PhoneSettings, Long> {

}

实体类,

@Entity
@Table(name = "phone_settings", catalog = "dialer")
public class PhoneSettings implements java.io.Serializable {

WebSecurityConfig 类,

@Configuration
@EnableWebMvcSecurity
@ComponentScan
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    /**
     * Instantiates a new web security config.
     */
    public WebSecurityConfig() {

        super();
    }

    /**
     * {@inheritDoc}
     * @see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(org.springframework.security.config.annotation.web.builders.HttpSecurity)
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
            .antMatchers("/login", "/logoffUser", "/sessionExpired", "/error", "/unauth", "/redirect", "*support*").permitAll()
            .anyRequest().authenticated().and().rememberMe().and().httpBasic()
            .and()
            .csrf()
            .disable().logout().deleteCookies("JSESSIONID").logoutSuccessUrl("/logoff").invalidateHttpSession(true);
    }


    @Autowired
    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {

      auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }

}

包如下,

  1. Application 班级在 - com.nervy.dialer
  2. Datasource 班级在 - com.nervy.dialer.common
  3. 实体类在 - com.nervy.dialer.domain
  4. 服务类在 - com.nervy.dialer.domain.service.impl
  5. 控制器位于 - com.nervy.dialer.spring.controller
  6. 存储库类位于 - com.nervy.dialer.spring.jpa.repository
  7. WebSecurityConfig 在 - com.nervy.dialer.spring.security

谢谢

【问题讨论】:

  • 我相信你仍然需要告诉 Hibernate 扫描你的实体对象的包。

标签: spring spring-mvc jpa spring-boot spring-data


【解决方案1】:

在 Spring Boot 入口点类中使用 @EntityScan 配置实体的位置。

2016 年 9 月更新:对于 Spring Boot 1.4+:
使用org.springframework.boot.autoconfigure.domain.EntityScan
而不是 org.springframework.boot.orm.jpa.EntityScan,因为 ...boot.orm.jpa.EntityScan 在 Spring Boot 1.4 中是 deprecated

【讨论】:

  • 这个选项也没有帮助。我想,我的配置中缺少其他内容。
  • 对我的情况也没有帮助。
  • 它确实对我有用,但它是一个已弃用的注释。
  • 谢谢胡安,我已经用当前版本的实体扫描更新了答案。
【解决方案2】:

尝试添加以下所有内容,在我的应用程序中它可以与 tomcat 正常工作

 @EnableJpaRepositories("my.package.base.*")
 @ComponentScan(basePackages = { "my.package.base.*" })
 @EntityScan("my.package.base.*")   

我正在使用 Spring Boot,当我使用嵌入式 tomcat 时,它在没有 @EntityScan("my.package.base.*") 的情况下工作正常,但是当我尝试将应用程序部署到外部 tomcat 时,我的实体出现 not a managed type 错误。

补充阅读:

@ComponentScan 用于扫描所有标记为@Controller, @Service, @Repository, @Component 等的组件...

@EntityScan 用于扫描所有标记为@Entity 的实体,以查找应用程序中配置的任何 JPA。

【讨论】:

  • 同上!为了让上述内容适用于我正在做的 POC,我只是将所有这些添加到我的 Spring Boot 应用程序注释中,并使用 com.* 作为匹配器 - 这似乎很容易解决我的所有类问题我有 2 个不同的 com.* 命名空间! @EnableJpaRepositories("com.*") @ComponentScan(basePackages = { "com.*" }) @EntityScan("com.*")
  • 非常适合我。看来@EntityScan 是必需的
  • 似乎 .* 不是必需的,因为它递归地进入扫描基本包内的所有内容
  • 应该没有星号*。它不会与它一起工作。
【解决方案3】:

我认为用@ComponentScan("com.nervy.dialer.domain") 替换@ComponentScan 会起作用。

编辑:

我添加了一个sample application 来演示如何使用 BoneCP 设置池数据源连接。

该应用程序与您的应用程序具有相同的结构。我希望这能帮助您解决配置问题

【讨论】:

  • 如果我添加@ComponentScan("com.nervy.dialer.domain"),我会得到数据源不喜欢的异常,因为它在不同的包中。还添加了该软件包,例如 @ComponentScan({"com.nervy.dialer.domain","com.nervy.dialer.common"})。现在得到同样的旧错误。
  • 我添加了一个示例应用程序来演示如何使用 BoneCP 设置池数据源连接。 github.com/azizunsal/SpringBootBoneCPPooledDataSource 该应用程序与您的应用程序具有相同的结构。我希望这能帮助您解决配置问题。
  • 你做到了。它工作正常。谢谢你的帮助。我在数据源中有以下注释。 @EnableJpaRepositories(entityManagerFactoryRef = "dialerEntityManagerFactory", transactionManagerRef = "dialerTransactionManager", basePackages = { "com.nervytech.dialer.repository"})。删除它并在 DialerApplication 中添加 @EnableJpsRespository 后,它开始正常工作。
  • 我也有同样的问题。 Spring boot 无法识别我的实体(来自 hibernate 4+ 版本的@DynamicUpdate)。我尝试在 ComponentScan 或 EntityScan 中添加我的模型包,但我得到了同样的错误。我在 Application 类中的注释是: SpringBootApplication ComponentScan(basePackages = {"com.example.controllers", "com.example.services", "com.example.models"}) EnableAutoConfiguration @Configuration @EnableJpaRepositories(basePackages = {"com. example.dao", "com.example.models"})
  • 与我们使用 Hibernate 作为 JPA 提供程序的场景相同。在尝试了所有这些解决方案之后,问题仍然存在。在我的应用程序配置文件中添加此配置为我解决了这个问题。 hibernate.annotation.packages.to.scan = ${myEntityPackage}
【解决方案4】:

如果您配置自己的 EntityManagerFactory Bean,或者如果您从另一个项目复制粘贴了此类持久性配置,则必须在 EntityManagerFactory 的配置中设置或调整包:

@Bean
public EntityManagerFactory entityManagerFactory() throws PropertyVetoException {
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setGenerateDdl(true);
    LocalContainerEntityManagerFactoryBean factory;
    factory = new LocalContainerEntityManagerFactoryBean();
    factory.setPackagesToScan("!!!!!!package.path.to.entities!!!!!");
    //...
}

注意“多个”需求,您需要一个字符串数组作为传递给 setPackagesToScan 的参数(而不是逗号分隔的单个字符串值)。下面说明了这个问题。

    String[] packagesArray = "com.mypackage1,com.mypackage2".split(",");
    em.setPackagesToScan(packagesArray);

【讨论】:

  • 注意,如果你必须为 setPackagesToScan 传入多个值,你传入一个字符串 [] 数组,而不是一个逗号分隔的包名列表。
  • Indeed "factory.setPackagesToScan 是关键解决方案,您必须在此处添加缺少的模型包名称。
  • 感谢您的多个需求部分 -> XML 配置接受逗号分隔的字符串,但出于某种原因基于 Java 的不接受。
【解决方案5】:

在我的情况下,问题是由于我忘记使用 @javax.persistence.Entity 注释来注释我的实体类。呵呵!

//The class reported as "not a amanaged type"
@javax.persistence.Entity
public class MyEntityClass extends my.base.EntityClass {
    ....
}

【讨论】:

【解决方案6】:

我收到这个错误是因为我写得很愚蠢

公共接口 FooBarRepository 扩展 CrudRepositoryRepository, Long> { ...

简要说明:通常创建一个 FooBarRepository 类来管理 FooBar 对象(通常表示表中称为 foo_bar 之类的数据)。在扩展 CrudRepository 以创建专用存储库类时,需要指定要管理的类型-- 在这种情况下,FooBar。但是,我错误地输入的是 FooBarRepository 而不是 FooBar。 FooBarRepository 不是我试图用 FooBarRepository 管理的类型(类)。因此,编译器会发出此错误。

我突出显示了 bold 输入错误。在我的示例中删除突出显示的单词 Repository 并且代码编译。

【讨论】:

  • 我无法恢复的生命中有 15 分钟
  • @TayabHussain,我用一些解释更新了帖子。希望对你有所帮助。
  • 你是个天才! :) 节省了我的时间。
【解决方案7】:

您可以使用 @EntityScan 注释并提供您的实体包来扫描您的所有 jpa 实体。您可以在使用 @SpringBootApplication 注解的基础应用程序类上使用此注解。

例如 @EntityScan("com.test.springboot.demo.entity")

【讨论】:

    【解决方案8】:

    永远不要忘记添加 @实体 在域类上

    【讨论】:

      【解决方案9】:

      将其放入您的 Application.java 文件中

      @ComponentScan(basePackages={"com.nervy.dialer"})
      @EntityScan(basePackages="domain")
      

      【讨论】:

      • 这是上述答案的副本。
      【解决方案10】:

      您在类定义中错过了@Entity,或者您有明确的组件扫描路径并且此路径不包含您的类

      【讨论】:

        【解决方案11】:

        我使用的是 Spring Boot 2.0,我通过将 @ComponentScan 替换为 @EntityScan 来解决此问题

        【讨论】:

          【解决方案12】:

          我遇到了同样的问题,但仅在运行需要 JPA 的 Spring Boot 测试用例时。最终结果是我们自己的 jpa 测试配置正在初始化 EntityManagerFactory 并设置要扫描的包。如果您手动设置,这显然会覆盖 EntityScan 参数。

              final LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
              factory.setJpaVendorAdapter( vendorAdapter );
              factory.setPackagesToScan( Project.class.getPackage().getName());
              factory.setDataSource( dataSource );
          

          重要提示:如果您仍然卡住,您应该在setPackagesToScan() 方法的org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager 中设置一个断点,并查看调用它的位置以及包是什么被传递给它。

          【讨论】:

            【解决方案13】:

            我已将我的应用程序类移至父包,例如:

            主类:com.job.application

            实体:com.job.application.entity

            这样你就不必添加@EntityScan

            【讨论】:

            • 这个答案对我有用。谢谢
            【解决方案14】:

            我在从 Spring boot 1.3.x 迁移到 1.5 时遇到了一些问题,我在 EntityManagerFactory bean 更新实体包后让它工作了

              @Bean(name="entityManagerFactoryDef")
              @Primary
              public LocalContainerEntityManagerFactoryBean defaultEntityManager() {
                  Map map = new HashMap();
                  map.put("hibernate.default_schema", env.getProperty("spring.datasource.username"));
                  map.put("hibernate.hbm2ddl.auto", env.getProperty("spring.jpa.hibernate.ddl-auto"));
                  LocalContainerEntityManagerFactoryBean em = createEntityManagerFactoryBuilder(jpaVendorProperties())
                          .dataSource(primaryDataSource()).persistenceUnit("default").properties(map).build();
                  em.setPackagesToScan("com.simple.entity");
                  em.afterPropertiesSet();
                  return em;
              }
            

            这个bean在Application类中引用如下

            @SpringBootApplication
            @EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryDef")
            public class SimpleApp {
            
            }
            

            【讨论】:

              【解决方案15】:

              不要像我一样犯明显的错误,让模板类型的顺序不正确。确保您没有在模板声明中首先使用 id,例如:

              public interface CapacityBasedProductRepository extends JpaRepository<Long, CapacityBasedProduct> {
              }
              

              JPA 类在前,id 列类型在后,如下所示:

              public interface CapacityBasedProductRepository extends JpaRepository<CapacityBasedProduct, Long> {
              }
              

              否则你会得到它抱怨java.lang.Long 是一个未知的实体类型。它使用第一项来查找要使用的实体。

              【讨论】:

                【解决方案16】:

                我有同样的问题,在 spring boot v1.3.x 版本中 我所做的是将 Spring Boot 升级到 1.5.7.RELEASE 版本。然后问题就解决了。

                【讨论】:

                • 我使用的是 1.3.x,然后我切换到 1.5.6 并遇到了问题
                【解决方案17】:

                我遇到了这个问题,因为我没有映射 orm.xml 文件中的所有实体

                【讨论】:

                  【解决方案18】:

                  面临类似的问题。 在我的情况下,存储库和被管理的类型不在同一个包中。

                  【讨论】:

                    【解决方案19】:

                    下面对我有用..

                    import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
                    import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
                    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
                    
                    import org.apache.catalina.security.SecurityConfig;
                    import org.junit.Before;
                    import org.junit.Test;
                    import org.junit.runner.RunWith;
                    import org.springframework.beans.factory.annotation.Autowired;
                    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
                    import org.springframework.boot.autoconfigure.domain.EntityScan;
                    import org.springframework.boot.test.context.SpringBootTest;
                    import org.springframework.context.annotation.ComponentScan;
                    import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
                    import org.springframework.test.context.junit4.SpringRunner;
                    import org.springframework.test.context.web.WebAppConfiguration;
                    import org.springframework.test.web.servlet.MockMvc;
                    import org.springframework.test.web.servlet.setup.MockMvcBuilders;
                    import org.springframework.web.context.WebApplicationContext;
                    
                    import com.something.configuration.SomethingConfig;
                    
                    @RunWith(SpringRunner.class)
                    @SpringBootTest(classes = { SomethingConfig.class, SecurityConfig.class }) //All your configuration classes
                    @EnableAutoConfiguration
                    @WebAppConfiguration // for MVC configuration
                    @EnableJpaRepositories("com.something.persistence.dataaccess")  //JPA repositories
                    @EntityScan("com.something.domain.entity.*")  //JPA entities
                    @ComponentScan("com.something.persistence.fixture") //any component classes you have
                    public class SomethingApplicationTest {
                    
                        @Autowired
                        private WebApplicationContext ctx;
                        private MockMvc mockMvc;
                    
                        @Before
                        public void setUp() {
                            this.mockMvc = MockMvcBuilders.webAppContextSetup(ctx).build();
                        }
                    
                        @Test
                        public void loginTest() throws Exception {
                            this.mockMvc.perform(get("/something/login"))
                            .andDo(print()).andExpect(status().isOk());
                        }
                    
                    }
                    

                    【讨论】:

                      【解决方案20】:

                      如果您正在使用多模块弹簧数据 JPA 项目。

                      如果您正在使用多个模块并且它们具有 Jpa 实体和存储库。这可能对你有用。我曾经在外部 tomcat 上部署时遇到“不是托管类型”错误(在嵌入式 tomcat 中从未遇到过)。

                      我有 1 个主模块和 2 个其他模块作为依赖项。当将主项目部署为战争时,我可以看到总共 3 个 Spring 应用程序正在初始化。当执行顺序是先主模块后子模块时,没有错误。但有时,子模块过去常常在主模块之前被调用。曾经导致“非托管类型实体异常”

                      棘手的是,错误不会出现在 spring boot 嵌入式 tomcat 中。但是当我们将它部署在外部 Tomcat 中时。这个例外过去来得太随机了。我必须多次部署同一场战争才能获得正确的命令。

                      我花了一整天的时间来解决这个问题。但结果问题出在我将其他模块作为依赖项添加到主模块中的方式上。如果在另一个项目中添加 spring boot 模块作为依赖项,请确保 jar 中不涉及主类。当您有另一个 Spring Boot 项目作为依赖项时,并且当您尝试将该项目部署为战争时。不保证主应用程序类的执行顺序。去掉主类,基本可以避免子模块的独立执行。因此,不会有任何执行顺序问题的空间。

                      【讨论】:

                        【解决方案21】:

                        对于未来的读者:

                        这是要扫描的多个包的语法糖。

                        注意,我的两个包也在不同的 jar 中,但包是主要驱动程序。只是记下我的 2 jar 情况。

                            em.setPackagesToScan(new String[] {"com.package.ONE.jpa.entities" , "com.package.TWO.jpa.entities"});
                        

                        我原来的错误代码如下:

                            em.setPackagesToScan("com.package.ONE.jpa.entities, com.package.TWO.jpa.entities");
                        

                        让我失望的是我的“xml to java-config swapover”。下面显示了一个简单的逗号分隔值。

                        逗号分隔的列表似乎适用于 di.xml,但不适用于“java config”。

                        Java,它是 ::: “什么时候是逗号分隔的,什么时候是字符串数组,什么时候是字符串可变参数”...... jig saw puzzle 有时让我发疯。

                            <!-- the value of "id" attribute below MUST BE "entityManagerFactory"  spring-data voodoo -->
                            <bean id="entityManagerFactory"
                                  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
                                <property name="dataSource" ref="dataSource"/>
                                <property name="packagesToScan" value="com.package.ONE.jpa.entities, com.package.TWO.jpa.entities"/>
                                <property name="jpaVendorAdapter">
                                    <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                                        <property name="showSql" value="${spring.jpa.show-sql}"/>
                                        <property name="generateDdl" value="${spring.jpa.generate-ddl}"/>
                                    </bean>
                                </property>
                                <!-- See https://stackoverflow.com/questions/16088112/how-to-auto-detect-entities-in-jpa-2-0/16088340#16088340 -->
                                <property name="jpaProperties">
                                    <props>
                                        <prop key="hibernate.hbm2ddl.auto">${spring.jpa.hibernate.ddl-auto}</prop>
                                        <prop key="hibernate.dialect">${spring.jpa.properties.hibernate.dialect}</prop>
                                    </props>
                                </property>
                            </bean>
                        

                        【讨论】:

                        • 方法setPackagesToScan接收一个vararg String参数,所以em.setPackagesToScan("com.package.ONE.jpa.entities", "com.package.TWO.jpa.entities");也有效。
                        • 啊,谢谢人族。语法糖再次来袭。
                        【解决方案22】:

                        我认为没有人提到它,而值得注意的是 Not a managed type 错误也可能是由包裹字母大小写引起的。 例如,如果要扫描的包名为myEntities,而我们在包扫描配置中提供myentities,那么它可能在一台机器上工作,而在另一台机器上不工作,所以要小心字母大小写。

                        【讨论】:

                          【解决方案23】:

                          将包添加到 @EntityScan 对我来说没有帮助,因为有一个工厂 bean 指定了包,所以必须在那里添加一个额外的条目。然后它开始工作了。

                          【讨论】:

                            【解决方案24】:

                            解决此问题的另一种方法是...包含 @SpringBootApplication 的类的包应该是根,所有其他包都应该是子包。例如:

                            package com.home
                            
                            @SpringBootApplication
                            public class TestApplication{
                              springapplication.run....
                            }
                             
                            package com.home.repo
                            
                            @Repository
                            public interface StudentRepo implements JpaRepository<Student, int>{
                             ..........
                            }
                            
                            package com.home.entity
                            
                            @Entity
                            @Table(name = "student")
                            public class Student{
                             ..........
                            }
                            

                            【讨论】:

                              猜你喜欢
                              • 2019-12-30
                              • 2022-08-07
                              • 1970-01-01
                              • 2019-02-07
                              • 2023-01-04
                              • 1970-01-01
                              • 1970-01-01
                              • 2018-02-25
                              • 1970-01-01
                              相关资源
                              最近更新 更多