Spring boot - 不是托管类型

时间:2015-02-22 22:28:14

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

我使用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 class is in - com.nervy.dialer
2) Datasource class is in - com.nervy.dialer.common
3) Entity classes are in - com.nervy.dialer.domain
4) Service classes are in - com.nervy.dialer.domain.service.impl
5) Controllers are in - com.nervy.dialer.spring.controller
6) Repository classes are in - com.nervy.dialer.spring.jpa.repository
7) WebSecurityConfig is in - com.nervy.dialer.spring.security

由于

20 个答案:

答案 0 :(得分:84)

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

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

答案 1 :(得分:56)

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

答案 2 :(得分:32)

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

编辑:

我添加了一个sample application来演示如何与BoneCP建立池数据源连接。

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

答案 3 :(得分:16)

在我的情况下,问题是由于我忘记使用@javax.persistence.Entity注释注释了我的Entity类。卫生署!

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

答案 4 :(得分:12)

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

e.g。 的 @EntityScan(&#34; com.test.springboot.demo.entity&#34)

答案 5 :(得分:7)

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

答案 6 :(得分:5)

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

答案 7 :(得分:4)

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

  

公共接口FooBarRepository扩展了CrudRepository 存储库,Long> {...

答案 8 :(得分:2)

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

}

答案 9 :(得分:1)

如果您已从另一个项目复制粘贴了持久性配置,则必须在 EntityManagerFactory 中手动设置包:

    @Bean
    public EntityManagerFactory entityManagerFactory() throws PropertyVetoException {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setPackagesToScan("!!!!!!misspelled.package.path.to.entities!!!!!");

        ....
    }

答案 10 :(得分:1)

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

主类:com.job.application

实体:com.job.application.entity

这样,您不必添加@EntityScan

答案 11 :(得分:1)

将此内容放入您的Application Java文件

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

答案 12 :(得分:0)

以下为我工作。

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

}

答案 13 :(得分:0)

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

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

重要注意事项:如果您仍然遇到问题,则应在org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager方法的setPackagesToScan()中设置一个断点,并查看在何处调用该断点以及正在传递哪些软件包。

答案 14 :(得分:0)

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

答案 15 :(得分:0)

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

答案 16 :(得分:0)

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

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

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

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

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

答案 17 :(得分:0)

对于未来的读者:

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

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

    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 到 java-config 交换”。下面显示了一个简单的逗号分隔值。

逗号分隔的列表似乎适用于 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>

答案 18 :(得分:-1)

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

答案 19 :(得分:-1)

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