ChatGPT解决这个技术问题 Extra ChatGPT

Spring Boot - 不是托管类型

我使用 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;

UserDetailsService 实现,

@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());
    }

}

包如下,

应用程序类在 - com.nervy.dialer 数据源类在 - com.nervy.dialer.common 实体类在 - com.nervy.dialer.domain 服务类在 - com.nervy.dialer.domain.service.impl控制器在 - com.nervy.dialer.spring.controller 存储库类在 - com.nervy.dialer.spring.jpa.repository WebSecurityConfig 在 - com.nervy.dialer.spring.security

谢谢

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

c
cellepo

在 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 是 deprecated Spring Boot 1.4 的


此选项也无济于事。我想,我的配置中缺少其他内容。
在我的情况下也没有帮助。
它确实对我有用,但它是一个已弃用的注释。
谢谢胡安,我已经用当前版本的实体扫描更新了答案。
m
manoj

尝试添加以下所有内容,在我的应用程序中它与 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
似乎 .* 不是必需的,因为它递归地进入扫描基本包内的所有内容
应该没有星号 *。它不会与它一起工作。
使用 asterick * 它不起作用。
a
azizunsal

我认为用 @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}
g
granadaCoder

如果您配置自己的 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 传入多个值,则传入字符串 [] 数组,而不是逗号分隔的包名称列表。
事实上,“factory.setPackagesToScan 是关键解决方案,您必须在此处添加缺少的模型包名称。
感谢您的多个需求部分 - > XML 配置接受逗号分隔的字符串,但由于某种原因基于 Java 的不接受。
V
Vladimir Shefer

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

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

在我的情况下,我还需要 @Entity 注释中的表名。我在这里设置了一个示例项目:github.com/mate0021/two_datasources.git
M
Marvo

我收到此错误是因为我愚蠢地写了

公共接口 FooBarRepository 扩展 CrudRepository { ...

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

我强调了粗体输入的错误位。在我的示例中删除突出显示的单词 Repository 并编译代码。


我生命中无法恢复的 15 分钟
@TayabHussain,我用一些解释更新了帖子。希望它可以帮助你。
你是个天才! :) 节省了我的时间。
这对我有帮助,谢谢。
N
Nitesh Saxena

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

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


M
Mohammad Badiuzzaman

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


V
Vladimir Shefer

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

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

这是上述答案的副本。
T
Tamer Awad

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


A
Arun Raaj

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


C
Chris Hinshaw

我遇到了同样的问题,但仅在运行需要 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 中设置一个断点,并查看调用它的位置以及传递给哪些包它。


T
Tushar Wason

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

主类:com.job.application

实体:com.job.application.entity

这样您就不必添加 @EntityScan


这个答案对我有用。谢谢
R
Randy

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

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

JPA 类是第一个,id 列类型是第二个,如下所示:

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

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


R
Ravi M

我从 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 {

}

p
pyb

就我而言,我错误地从 jakarta.persistence-api 导入类。

javax.persistence.* 导入对我有用:

package foo;
import javax.persistence.Entity;

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

P
Procrastinator

就我而言,我犯了使用存储库类作为 JpaRepository 参数而不是实体类的错误。像这样:

@Repository
public interface BuyerInspectionRepository extends JpaRepository<BuyerInspectionRepository,Long> {

}

所以我用实体类替换了存储库类。这是买方检查。

@Repository
public interface BuyerInspectionRepository extends JpaRepository<BuyerInspection,Long> {

}

M
Maosheng Wang

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


我在 1.3.x 上,然后我切换到 1.5.6 并遇到了问题
P
Pavlo Zvarych

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


佚名

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


它们不需要在同一个包中。事实上,它们不应该在同一个包中。
R
Raphael Amoedo

下面为我工作..

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());
    }

}

J
John_Wick

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

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

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

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

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


g
granadaCoder

对于未来的读者:

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

请注意,我的两个包也在不同的 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 接收可变参数字符串参数,因此 em.setPackagesToScan("com.package.ONE.jpa.entities", "com.package.TWO.jpa.entities"); 也有效。
啊,谢谢人族。语法糖再次罢工。
T
Tomasz S

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


x
xbranko

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


B
Barani r

解决此问题的另一种方法是...包含 @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{
 ..........
}

i
invzbl3

我用 Not a managed type 重现了类似的问题。

进一步来说:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'stockPriceRepository' defined in com.example.stockclient.repository.StockPriceRepository defined in @EnableJpaRepositories declared on StockUiApplication: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class com.example.stockclient.StockPrice

由于我有多模块项目,我需要为需要知道 JPA 存储库路径的 Spring Data JPA 启用自动配置支持,因为默认情况下,它将仅扫描主应用程序包及其子包以检测 {2 } 存储库。

因此,在我的特定用例中,我已经使用 @EnableJpaRepositories 来启用包含必要包但没有 @EntityScanJPA 存储库。

@EntityScan@EnableJpaRepositories 的情况相同,因为实体类没有放在主应用程序包中,因为是多模块项目。

例如,有关更多详细信息,您可以参考此 article


T
Toni Nagy

如果您使用 SessionFactory 作为 EMF:

在我的情况下,问题是我忘记将新的实体类型包含在 Hibernate 配置中作为带注释的类,我得到了错误。

因此,在您的 SessionFactory bean 中,不要忘记为您的新实体类型包含这一行:

configuration.addAnnotatedClass(MyEntity.class);

A
Andrei Manolache

在我的例子中,我有一个多 maven 模块项目,其中一个是 model 包,其他的是 microservices。在我的例子中,当我运行一个使用在 model package(我的项目中调用的域)中定义的类的微服务时,我必须将 @EntityScan(basePackages = {"com.example.domain"}) 注释添加到 @SpringBootApplication class

@SpringBootApplication
@EnableEurekaClient
@EntityScan(basePackages = {"com.example.domain"}) // add this so the spring boot context knows where to look after entities
public class DoctorServiceApplication {

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

}

我知道这个问题之前已经回答过了,但我觉得我需要强调这个问题在处理多模块 Maven 项目时可能经常发生