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

谢谢


当前回答

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

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

其他回答

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

公共接口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,代码将被编译。

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

主类:com.job.application

实体:com.job.application.entity

这样你就不必添加@ entitscan了

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

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

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

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

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

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

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