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

谢谢


当前回答

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

其他回答

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

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

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

尝试添加以下所有内容,在我的应用程序中,它与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在您的应用程序。

如果您正在使用多模块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.

如果你配置了你自己的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);