Spring Boot - 不是一个受管理的类型。

270

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

用户详细信息服务实现,

@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 类位于 - com.nervy.dialer
  2. Datasource 类位于 - com.nervy.dialer.common
  3. 实体类位于 - com.nervy.dialer.domain
  4. 服务类位于 - com.nervy.dialer.domain.service.impl
  5. 控制器位于 - com.nervy.dialer.spring.controller
  6. 仓库类位于 - com.nervy.dialer.spring.jpa.repository
  7. WebSecurityConfig 位于 - com.nervy.dialer.spring.security

谢谢!


1
我相信你仍然需要告诉Hibernate扫描包以寻找你的实体对象。 - chrylis -cautiouslyoptimistic-
33个回答

0
我正在进行使用 Kotlin 编写的 Spring Web 应用程序教程, 但是遇到了问题。通过与官方 GitHub 存储库的对比,我意识到自己的 Entities.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中没有收到任何警告。


0

针对未来读者:

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

请注意,我的两个包也在不同的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及其“何时为逗号分隔,何时为字符串数组,何时为字符串可变参数”……这个拼图有时让我发疯。
    <!-- 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://dev59.com/ImQo5IYBdhLWcg3wZepg#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>

1
方法 setPackagesToScan 接收一个可变参数的字符串,因此 em.setPackagesToScan("com.package.ONE.jpa.entities", "com.package.TWO.jpa.entities"); 也可以工作。 - Terran
1
啊,谢谢Terran。语法糖又来了。 - granadaCoder

-1

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


使用 @EntityScan 的答案已经被多次给出,例如 invzbl3。你的回答是一个没有增加价值的重复。考虑将其删除,并将“指定包的工厂bean”的情况作为注释添加到现有答案之一中。 - hc_dev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接