Error creating bean with name 'bookshelfController': Unsatisfied dependency expressed through field 'bookshelfService';

Пытаюсь реализовать отправку с клиента на сервер некоторых полей, указанных в UploadedBook и .pdf файла, конвертированного в MultipartFile. Код ошибки

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bookshelfRepository' defined in ru.senchenko.spring.demo.DB.DAO.BookshelfDAO.BookshelfRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract java.lang.Long ru.senchenko.spring.demo.DB.DAO.BookshelfDAO.BookshelfRepository.countByBook(java.lang.String)! No property book found for type UploadedBook! at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1786) ~[spring-beans-5.3.5.jar:5.3.5]

Файл UploadedBookDTO

package ru.senchenko.spring.demo.API.DTO.UploadedBook;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UploadedBookDTO {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long id;

  @NotNull @NotBlank public String author;
  @NotNull @NotBlank public String title;
  @NotNull @NotBlank public String publish_date;
  @NotNull @NotBlank public byte[] file_data;

}

Файл BookshelfController

package ru.senchenko.spring.demo.API.REST.BookshelfController;


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import ru.senchenko.spring.demo.API.DTO.UploadedBook.UploadedBookDTO;
import ru.senchenko.spring.demo.SRV.BookshelfService.BookshelfService;

@Slf4j
@RestController
@RequestMapping("bookshelf")
public class BookshelfController {
  @Autowired private BookshelfService bookshelfService;

  @RequestMapping(
      value = "/add",
      method = RequestMethod.POST,
      consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
  public void savingBook(UploadedBookDTO uploadedBookDTO) {
    log.info("[BookshelfController.savingBook] uploadedBookDTO = {}", uploadedBookDTO);
    bookshelfService.savingBook(uploadedBookDTO);
  }
  ;
}

Файл BookshelfDAO

package ru.senchenko.spring.demo.DB.DAO.BookshelfDAO;


import org.mapstruct.factory.Mappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import ru.senchenko.spring.demo.API.DTO.UploadedBook.UploadedBookDTO;
import ru.senchenko.spring.demo.SRV.Mapper.BookshelfMapper.BookshelfMapper;

@Component
public class BookshelfDAO {
  private final BookshelfMapper bookshelfMapper = Mappers.getMapper(BookshelfMapper.class);

  @Autowired private BookshelfRepository bookshelfRepository;

  public void bookSaving(UploadedBookDTO uploadedBookDTO) {
    bookshelfRepository.save(bookshelfMapper.toEntity(uploadedBookDTO));
  }
}

Файл BookshelfRepository

package ru.senchenko.spring.demo.DB.DAO.BookshelfDAO;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import ru.senchenko.spring.demo.DB.Entity.UploadedBook;

@Repository
public interface BookshelfRepository extends CrudRepository<UploadedBook, Long> {
  Long countByBook(String author);
}

Файл UploadedBook

package ru.senchenko.spring.demo.DB.Entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;

@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "my_bookshelf")
public class UploadedBook {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long id;

  @Column(name = "author")
  private String author;

  @Column(name = "title")
  private String title;

  @Column(name = "publish_date")
  private String publish_date;

  @Column(name = "file_data")
  private byte[] file_data;
}

Файл BookshelfSerivce

package ru.senchenko.spring.demo.SRV.BookshelfService;

import org.springframework.stereotype.Service;
import ru.senchenko.spring.demo.API.DTO.UploadedBook.UploadedBookDTO;

@Service
public interface BookshelfService {
  public void savingBook(UploadedBookDTO uploadedBookDTO);
}

Файл BookshelfServiceImpl

    package ru.senchenko.spring.demo.SRV.BookshelfService;
    
    
    import lombok.AllArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Service;
    import ru.senchenko.spring.demo.API.DTO.UploadedBook.UploadedBookDTO;
    import ru.senchenko.spring.demo.DB.DAO.BookshelfDAO.BookshelfDAO;
    import ru.senchenko.spring.demo.DB.DAO.BookshelfDAO.BookshelfRepository;
    
    @Slf4j
    @Service
    @AllArgsConstructor
    public class BookshelfServiceImpl implements BookshelfService {
        private final BookshelfDAO bookshelfDAO;
        private final BookshelfRepository bookshelfRepository;
    
        public void savingBook(UploadedBookDTO uploadedBookDTO) {
            log.info("[BookshelfServiceImpl.savingBook] uploadedBookDTO = {}", uploadedBookDTO);
            bookshelfDAO.bookSaving(uploadedBookDTO);
        }
    }
Файл **BookshelfMapper**
package ru.senchenko.spring.demo.SRV.Mapper.BookshelfMapper;

import org.mapstruct.Mapper;
import ru.senchenko.spring.demo.API.DTO.UploadedBook.UploadedBookDTO;
import ru.senchenko.spring.demo.DB.Entity.UploadedBook;

@Mapper
public interface BookshelfMapper {
    UploadedBookDTO toDTO(UploadedBook uploadedBook);
    UploadedBook toEntity(UploadedBookDTO uploadedBookDTO);
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>ru.senchenko.spring</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Diplom</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>11</java.version>
    </properties>

    <dependencies>

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

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

        <!-- https://mvnrepository.com/artifact/com.mashape.unirest/unirest-java -->
        <dependency>
            <groupId>com.mashape.unirest</groupId>
            <artifactId>unirest-java</artifactId>
            <version>1.4.9</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.2.20</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>provided</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.4.32.Final</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.4.32.Final</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-jpa -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>2.5.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>2.5.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct -->
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.4.2.Final</version>
        </dependency>



    </dependencies>


    <build>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.19.1</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>15</source>
                    <target>15</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>1.18.20</version>
                        </path>
                        <!-- This is needed when using Lombok 1.18.16 and above -->
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok-mapstruct-binding</artifactId>
                            <version>0.2.0</version>
                        </path>
                        <!-- Mapstruct should follow the lombok path(s) -->
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>1.4.2.Final</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>

        </plugins>
    </build>

</project>

Ответы (1 шт):

Автор решения: Roman Konoval

Ключевая часть сообщения об ошибке:

Failed to create query for method public abstract java.lang.Long ru.senchenko.spring.demo.DB.DAO.BookshelfDAO.BookshelfRepository.countByBook(java.lang.String)! No property book found for type UploadedBook!

Из нее видно, что проблема в определении метода в репозитории:

Long countByBook(String author);

Этот метод указывает спрингу, что вы хотите отфильтровать объекты UploadedBook по полю book (часть после By), и потом посчитать их количество. В UploadedBook нет такого поля (об этом говорит ошибка).

Наверно, вы хотели фильтровать по автору (судя по названию поля). Замените на:

Long countByAuthor(String author);
→ Ссылка