我使用 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
谢谢
在 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 的
尝试添加以下所有内容,在我的应用程序中它与 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。
com.*
作为匹配器 - 这似乎很容易解决我的所有类的情况我有 2 个不同的 com.*
命名空间! @EnableJpaRepositories("com.*") @ComponentScan(basePackages = { "com.*" }) @EntityScan("com.*")
*
。它不会与它一起工作。
我认为用 @ComponentScan("com.nervy.dialer.domain")
替换 @ComponentScan
会起作用。
编辑 :
我添加了一个 sample application 来演示如何使用 BoneCP 设置池数据源连接。
该应用程序与您的应用程序具有相同的结构。我希望这将帮助您解决配置问题
如果您配置自己的 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);
在我的情况下,问题是由于我忘记使用 @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
我收到此错误是因为我愚蠢地写了
公共接口 FooBarRepository 扩展 CrudRepository
简要说明:通常创建一个 FooBarRepository 类来管理 FooBar 对象(通常表示表中称为 foo_bar 之类的数据)。当扩展 CrudRepository 以创建专门的存储库类时,需要指定正在管理的类型 - 在这种情况下,FooBar。但是,我错误地输入的是 FooBarRepository 而不是 FooBar。 FooBarRepository 不是我试图用 FooBarRepository 管理的类型(类)。因此,编译器会发出此错误。
我强调了粗体输入的错误位。在我的示例中删除突出显示的单词 Repository 并编译代码。
您可以使用 @EntityScan 注释并提供您的实体包来扫描您的所有 jpa 实体。您可以在使用 @SpringBootApplication 注释的基础应用程序类上使用此注释。
例如@EntityScan("com.test.springboot.demo.entity")
永远不要忘记在域类上添加@Entity
将其放入您的 Application.java
文件中
@ComponentScan(basePackages={"com.nervy.dialer"})
@EntityScan(basePackages="domain")
您在类定义中错过了@Entity,或者您有明确的组件扫描路径并且此路径不包含您的类
我正在使用 Spring Boot 2.0,我通过将 @ComponentScan 替换为 @EntityScan
来解决此问题
我遇到了同样的问题,但仅在运行需要 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
中设置一个断点,并查看调用它的位置以及传递给哪些包它。
我已将我的应用程序类移至父包,例如:
主类:com.job.application
实体:com.job.application.entity
这样您就不必添加 @EntityScan
不要像我一样犯一个明显的错误,让模板类型的顺序不正确。确保您在模板化声明中没有首先使用 id,例如:
public interface CapacityBasedProductRepository extends JpaRepository<Long, CapacityBasedProduct> {
}
JPA 类是第一个,id 列类型是第二个,如下所示:
public interface CapacityBasedProductRepository extends JpaRepository<CapacityBasedProduct, Long> {
}
否则你会得到它抱怨 java.lang.Long
是一个未知的实体类型。它使用第一项来查找要使用的实体。
我从 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 {
}
就我而言,我错误地从 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 {
// ...
}
就我而言,我犯了使用存储库类作为 JpaRepository 参数而不是实体类的错误。像这样:
@Repository
public interface BuyerInspectionRepository extends JpaRepository<BuyerInspectionRepository,Long> {
}
所以我用实体类替换了存储库类。这是买方检查。
@Repository
public interface BuyerInspectionRepository extends JpaRepository<BuyerInspection,Long> {
}
我有同样的问题,在 spring boot v1.3.x 版本中,我所做的是将 spring boot 升级到版本 1.5.7.RELEASE。然后问题就解决了。
我遇到了这个问题,因为我没有映射 orm.xml 文件中的所有实体
面临类似的问题。在我的情况下,存储库和被管理的类型不在同一个包中。
下面为我工作..
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());
}
}
如果您正在使用多模块弹簧数据 JPA 项目。
如果您正在使用多个模块并且它们具有 Jpa 实体和存储库。这可能对你有用。我曾经在外部 tomcat 上部署时遇到“不是托管类型”错误(在嵌入式 tomcat 中从未遇到过)。
我有 1 个主模块和 2 个其他模块作为依赖项。当将主项目部署为战争时,我可以看到总共 3 个 Spring 应用程序正在初始化。当执行顺序是先主模块后子模块时,没有错误。但有时,子模块过去常常在主模块之前被调用。这曾经导致“不是托管类型实体异常”
棘手的是,错误不会出现在 spring boot 嵌入式 tomcat 中。但是当我们将它部署在外部 tomcat 中时。这个例外过去来得太随机了。我必须多次部署同一场战争才能获得正确的命令。
我花了一整天的时间试图解决这个问题。但事实证明,问题在于我将其他模块作为依赖项添加到主模块中的方式。如果要在另一个项目中添加 spring boot 模块作为依赖项,请确保 jar 中不涉及主类。当您有另一个 Spring Boot 项目作为依赖项时,并且当您尝试将该项目部署为战争时。不保证主应用程序类的执行顺序。去掉主类,基本可以避免子模块的独立执行。因此,不会有任何执行顺序问题的空间。
对于未来的读者:
这是要扫描的多个包的语法糖。
请注意,我的两个包也在不同的 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");
也有效。
我认为没有人提到它,而值得注意的是, Not a managed type
错误也可能是由包裹字母大小写引起的。例如,如果要扫描的包被称为 myEntities
,而我们在包扫描配置中提供 myentities
,那么它可能在一台机器上工作,而在另一台机器上不工作,所以要小心字母大小写。
在我的情况下,将包添加到 @EntityScan
没有帮助,因为有一个指定包的工厂 bean,所以必须在那里添加一个额外的条目。然后它开始工作。
解决此问题的另一种方法是...包含 @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{
..........
}
我用 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
来启用包含必要包但没有 @EntityScan
的 JPA
存储库。
@EntityScan
与 @EnableJpaRepositories
的情况相同,因为实体类没有放在主应用程序包中,因为是多模块项目。
例如,有关更多详细信息,您可以参考此 article。
如果您使用 SessionFactory 作为 EMF:
在我的情况下,问题是我忘记将新的实体类型包含在 Hibernate 配置中作为带注释的类,我得到了错误。
因此,在您的 SessionFactory bean 中,不要忘记为您的新实体类型包含这一行:
configuration.addAnnotatedClass(MyEntity.class);
在我的例子中,我有一个多 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 项目时可能经常发生