【问题标题】:Spring - CrudRepository is not createdSpring - CrudRepository 未创建
【发布时间】:2018-07-12 18:39:26
【问题描述】:

CrudRepository 豆

@Repository
public interface UserDao extends CrudRepository<User, Long>
{
    List<User> findByFirstNameAndLastName(String firstName, String lastName);
} 

对于User 资源

@Entity
@Table(name="User")
public class User 
{
    @Id
    @GeneratedValue
    private long id;

    @Column(name="first_name")
    private String firstName;

    @Column(name="last_name")
    private String lastName;

    /* --- Getters,setters,default constructor -------*/
}

在我启动 Spring Boot 应用程序时未创建

Field dao in base.package.service.UserService required a bean 
of type 'base.package.dao.UserDao' that could not be found.

但包裹肯定会被扫描

@SpringBootApplication(scanBasePackages= {"base.package"})

我强烈怀疑它与我正在使用的嵌入式数据库h2 有关系。我正在尝试在schema.sql 中创建User 表

CREATE TABLE IF NOT EXISTS User (
    id   INTEGER      NOT NULL AUTO_INCREMENT,
    first_name VARCHAR(128) NOT NULL,
    last_name VARCHAR(128) NOT NULL,
    PRIMARY KEY (id)
);

但一旦我取消注释 IF NOT EXISTS 它就会引发错误(表已经存在)。所以这首先意味着 spring 负责创建模式。但我觉得表没有重新创建,因为在data.sql 脚本中

INSERT INTO User (id,first_name,last_name) VALUES (1,'Vincent', 'Vega');

我总是必须在启动时手动增加id,否则我会得到一个

org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.USER(ID)"

这里是来自application.properties 的 jpa 属性

# below properties create schema, so schema.sql is redundant
spring.jpa.generate-ddl=true  
spring.jpa.hibernate.ddl-auto=create-drop
spring.datasource.initialization-mode=always
spring.jpa.database=H2
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.show-sql=true
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:~/testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE


spring.datasource.name=testdb
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

我认为启动时永远不会重新创建表的原因是因为我在应用关闭时收到此错误

2018-02-02 09:27:47.907 INFO  [restartedMain] [StandardService] Stopping service [Tomcat]
2018-02-02 09:27:47.907 WARN  [localhost-startStop-1] [WebappClassLoaderBase] The web application [ROOT] appears to have started a thread named [MVStore background writer nio:C:/Users/user/testdb.mv.db] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 java.lang.Object.wait(Native Method)

这后面是UserDao bean 没有创建的异常。

***************************
APPLICATION FAILED TO START
***************************

Description:

Field dao in base.package.user.service.UserService required a bean of type 'base.package.user.dao.UserDao' that could not be found.


Action:

Consider defining a bean of type 'base.package.user.dao.UserDao' in your configuration.

POM.XML

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.M7</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.M5</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
       /* .... */

编辑

这里是UserService

@Service
public class UserService 
{
    @Autowired private UserDao dao;

    public List<User> findByFirstNameAndLastName(String firstName, String lastName)
    {
        return dao.findByFirstNameAndLastName(firstName, lastName);
    }

    public User save(final User user)
    {
        return dao.save(user);
    }
}

编辑 2

现在我得到了

Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.project.bot.user.User
    at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:472)
    at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:72)
    at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:66)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:169)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:107)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:90)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:300)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$3(RepositoryFactoryBeanSupport.java:287)
    at org.springframework.data.util.Lazy.getNullable(Lazy.java:141)
    at org.springframework.data.util.Lazy.get(Lazy.java:63)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:290)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:102)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1769)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1706)
    ... 102 common frames omitted

【问题讨论】:

  • 你试过了吗:公共接口 UserDao extends JpaRepository
  • UserService 长什么样子?
  • @rocksteady 请查看编辑
  • @MatMat 不,但它昨天与 CrudRepository 一起工作,我很困惑
  • package 应该是保留字段,你需要更改你的包名。

标签: java spring spring-mvc spring-data-jpa h2


【解决方案1】:

未创建的表不应该对bean是否定义有任何影响。

我认为您在这里遇到的问题是您没有实例化您的存储库 bean。 Spring Data JPA 存储库 bean 不会被组件扫描拾取,因为它们只是接口。 @Repository 注解在这里实际上什么都不做。

如果您在配置中提供了@EnableJpaRepositories,则动态创建 Spring Data JPA repo bean。

您可能还需要放置一个@EntityScan 以确保您的所有@Entity 都被 Spring 识别

@SpringBootApplication(scanBasePackages= {"base.package"})
@EnableJpaRepositories("base.package")
@EntityScan("base.package")

【讨论】:

  • @Repository 注释应该做一些事情,因为它包含组件对吗?所以一个简单的 ComponentScan 应该可以把它捡起来
  • 否,因为 Spring 数据存储库是特殊的。它们只是接口,因此不能定义为@Components。 Spring 数据根据您定义的存储库动态创建具体实现。但是,如果您有 @EnableJpaRepositories 注释,它只会生成这些具体的 bean
  • @tenticon 我编辑了我的帖子,回答了你的第二个问题
猜你喜欢
  • 1970-01-01
  • 2014-12-30
  • 2021-08-21
  • 2014-06-24
  • 2017-07-04
  • 2014-06-13
  • 2017-04-25
  • 2016-07-01
  • 1970-01-01
相关资源
最近更新 更多