Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring - CrudRepository is not created

The CrudRepository bean

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

for the User resource

@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 -------*/
}

is not created when I start my Spring boot app

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

but the packages are definitely scanned

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

I got the strong suspicion that it has to do something with the embedded database h2 that I am using. I am trying to create the User table in schema.sql

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

but as soon as I uncomment IF NOT EXISTS it throws an error (table already exists). So this firstly means that spring takes charge of created the schema. But I get the feeling that the table is not recreated because in the data.sql script

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

I always have to manually increment the id on startup otherwise i get a

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

Here are the jpa properties from application.properties

# 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

The reason why I think that the table is never recreated on startup is because I get this error when the app closes

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)

This is followed by the exception that UserDao bean is not created.

***************************
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>
       /* .... */

EDIT

Here is the 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);
    }
}

EDIT 2

Now I am getting

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
like image 808
tenticon Avatar asked Feb 02 '18 09:02

tenticon


People also ask

Is CrudRepository a part of Spring data JPA?

CrudRepository and JPA repository both are the interface of the spring data repository library. Spring data repository reduces the boilerplate code by providing some predefined finders to access the data layer for various persistence layers. JPA repository extends CrudRepository and PagingAndSorting repository.

Is CrudRepository transactional by default?

You are right. Only CRUD methods ( CrudRepository methods) are by default marked as transactional. If you are using custom query methods you should explicitly mark it with @Transactional annotation.

Does @repository create a bean?

1. @Repository Annotation. In the spring framework, @Component annotation marks a Java class as a bean so the component-scanning mechanism can find it and create its instance into the application context.

How to use crudrepository in spring?

CrudRepository provides generic CRUD operation on a repository for a specific type. CrudRepository is a Spring data interface and to use it we need to create our interface by extending CrudRepository. Spring provides CrudRepository implementation class automatically at runtime.

Why is crudrepository not working?

We generally get this type of error when we create the repository as class instead of interface. CrudRepository is an interface, you most probably extend it using an interface only: Wrong (Some times when we create the repository we create a class by mistake ): You might want to read again the question as I already had an interface and not a class.

Is crudrepository a class or interface?

CrudRepository is an interface not a class. Replace extends with implements. That's wrong. Interfaces extend other interfaces. They do not implement them. As Markus said!

How to add custom CRUD methods in extended crudrepository?

b. Read : 5. Custom Repository Methods CrudRepository provides methods for generic CRUD operation and if we want to add custom methods in our interface that has extended CrudRepository, we can add in following ways. a. We can start our query method names with find...By, read...By, query...By, count...By, and get...By.


1 Answers

The table not being created should not have any impact on whether the bean is defined or not.

I think the problem you have here is that you are not instatiating your repository beans. Spring Data JPA repository beans are not picked up by component scans since they are only interfaces. The @Repository annotation actually does nothing here.

Spring Data JPA repo beans are created dynamically provided you have supplied the @EnableJpaRepositories in your configuration.

You may also need to put an @EntityScan to make sure all your @Entity's are recognised by Spring

@SpringBootApplication(scanBasePackages= {"base.package"})
@EnableJpaRepositories("base.package")
@EntityScan("base.package")
like image 161
Plog Avatar answered Oct 03 '22 04:10

Plog