我使用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进行连接池,数据源配置如下:

@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. nerve .dialer中 数据源类在- com. nerver .dialer.common中 实体类在- com. nerver .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

谢谢


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

编辑:

我已经添加了一个示例应用程序来演示如何使用BoneCP设置池化数据源连接。

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


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

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被弃用


尝试添加以下所有内容,在我的应用程序中,它与tomcat一起工作很好

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

我正在使用spring引导,当我使用嵌入式tomcat时,它可以很好地使用@EntityScan(“my.package.base.*”),但当我试图将应用程序部署到外部tomcat时,我没有得到我的实体的托管类型错误。

额外的阅读:

@ComponentScan用于扫描所有标记为@控制器、@服务、@存储库、@组件等的组件。

其中@ entitscan用于扫描所有您的实体,这些被标记为@Entity的任何配置JPA在您的应用程序。


在我的案例中,问题是由于我忘记用@javax.persistence注释我的Entity类。实体注释。哎!

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

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

如。 @EntityScan(“com.test.springboot.demo.entity”)


你要么错过了类定义上的@Entity,要么你有显式的组件扫描路径,而这个路径不包含你的类


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


我正在使用spring boot 2.0,我通过用@EntityScan替换@ComponentScan来修复这个问题


别忘了加上 @ entity 关于域类


如果你配置了你自己的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!!!!!");
    //...
}

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

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

下面对我有用。

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

}

我得到这个错误是因为我愚蠢地写了

公共接口FooBarRepository扩展CrudRepository<FooBarRepository, Long>{…

A brief explanation: One typically creates a FooBarRepository class to manage FooBar objects (often representing data in a table called something like foo_bar.) When extending the CrudRepository to create the specialized repository class, one needs to specify the type that's being managed -- in this case, FooBar. What I mistakenly typed, though, was FooBarRepository rather than FooBar. FooBarRepository is not the type (the class) I'm trying to manage with the FooBarRepository. Therefore, the compiler issues this error.

我用粗体突出显示了输入错误的地方。在我的示例中删除突出显示的单词Repository,代码将被编译。


我也遇到了同样的问题,但只是在运行需要JPA的spring引导测试用例时。最终的结果是,我们自己的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中设置一个断点,并查看它被调用的位置以及传递给它的包是什么。


把它放到你的Application.java文件中

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

从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在应用程序类中引用如下

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

}

我已经将我的应用程序类移动到父包,如下:

主类:com.job.application

实体:com.job.application.entity

这样你就不必添加@ entitscan了


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


如果您正在使用多模块spring数据jpa项目。

如果您正在处理多个模块,并且它们有Jpa实体和存储库。这可能对你有用。我曾经在外部tomcat上部署时得到一个“Not a managed type”错误(在嵌入式tomcat中从未遇到过)。

我有一个主模块和另外两个依赖模块。当将主项目部署为war时,我可以看到总共有3个Spring应用程序正在初始化。当执行顺序是Main模块先执行,然后是子模块时,就不会出现错误。但有时,子模块通常在主模块之前被调用。这通常会导致“非托管类型实体异常”

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

I spent the whole day trying to solve the issue. But turned out the problem was with the way I added my other modules as a dependency in the Main module. If you are adding the spring boot module as a dependency in another project, make sure that the main class is not involved in the jar. When you have another spring boot project as a dependency and when you try to deploy the project as a war. The order of execution of the main application class is not guaranteed. Removing the main class will basically avoid the independent execution of child modules. Hence, there won't be any room for order of execution issue.


对于未来的读者:

下面是用于扫描多个包的语法糖。

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

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

我原来的ERRANT代码如下:

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

让我困惑的是我的“xml到java配置切换”。下面显示了一个简单的用逗号分隔的值。

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

Java,它是:::"当它是逗号分隔,当它是字符串数组,当它是字符串变参数".......吉格锯拼图有时会把我逼疯。

    <!-- 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>

我想没有人提到,但值得注意的是,不是一个托管的类型错误也可能由包裹信件的情况。 例如,如果要扫描的包被称为myEntities,而我们在包扫描配置中提供了myEntities,那么它可能在一台机器上工作,而在另一台机器上则不能工作,因此要小心大小写。


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


不要像我一样犯明显的错误,让模板类型的顺序不正确。确保你在模板声明中没有把id放在前面,比如:

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

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

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

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


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

我已经复制了类似的问题w/不是管理类型。

更具体地说:

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

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

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

使用@EntityScan与使用@ enablejparepository情况相同,因为由于多模块项目,实体类没有放在主应用程序包中。

要了解更多细节,您可以参考这篇文章。


在我的例子中,我错误地从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 {
   // ...
}

如果您正在使用SessionFactory作为EMF:

在我的例子中,问题是我忘记在Hibernate配置中包含一个带注释的类的新实体类型,为此我得到了错误。

所以,在你的SessionFactory bean中,不要忘记为你的新实体类型添加这一行:

configuration.addAnnotatedClass(MyEntity.class);

在我的例子中,我犯了一个错误,使用存储库类作为JpaRepository参数,而不是实体类。是这样的:

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

}

所以我用实体类替换了存储库类。即买方检验。

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

}

多模块Maven项目

我知道@ entitscan之前被回答:

invzbl3 Manish Maheshwari

但我觉得有必要强调,在处理多模块Maven项目时,这个问题可能经常发生。

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

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

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

}

我能够通过在应用程序中添加以下内容来解决这个问题。属性文件。

spring.jpa.packagesToScan=你的实体文件夹的路径,比如com.java.entity


根据我的经验,您应该检查您的注释。如果将其用作bean,则必须使用@Component。但是作为存储库中的实体,您应该在类上面使用@Entity。


我在用Kotlin做Spring web应用程序教程时,遇到了这个问题。在与官方GitHub存储库进行了一些比较后,我意识到我的错误:我的实体。Kt文件缺少它的包指令。所以我有以下(注意缺少包指令):

import com.example.blog.toSlug
import java.time.LocalDateTime
import javax.persistence.*

@Entity
class Article(
    var title: String,
    var headline: String,
    var content: String,
    @ManyToOne var author: User,
    var slug: String = title.toSlug(),
    var addedAt: LocalDateTime = LocalDateTime.now(),
    @Id @GeneratedValue var id: Long? = null)

@Entity
class User(
    var login: String,
    var firstname: String,
    var lastname: String,
    var description: String? = null,
    @Id @GeneratedValue var id: Long? = null)

而不是正确的

package com.example.blog

import java.time.LocalDateTime
import javax.persistence.*

@Entity
class Article(
    var title: String,
    var headline: String,
    var content: String,
    @ManyToOne var author: User,
    var slug: String = title.toSlug(),
    var addedAt: LocalDateTime = LocalDateTime.now(),
    @Id @GeneratedValue var id: Long? = null)

@Entity
class User(
    var login: String,
    var firstname: String,
    var lastname: String,
    var description: String? = null,
    @Id @GeneratedValue var id: Long? = null)

奇怪的是,我没有从IntelliJ得到任何警告。


你可以查一下java版本,我的问题改了版本就解决了。

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.1</version>
    <relativePath />
</parent>

在Spring Version 6和JDK 17中,我得到了这个问题,当我使用jakarta.persist . entity时,我正在使用javax. persistence . entity,这个问题得到了解决