Создать пользовательский репозиторий для Spring Data JPA - PullRequest
0 голосов
/ 25 декабря 2018

Я пытаюсь создать custom repository, следуя этому руководству: https://www.baeldung.com/spring-data-jpa-method-in-all-repositories

Сбой сборки моего приложения с ошибкой:

NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.dao.ExtendedStudentRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Мой полный исходный код: https://github.com/sesong11/springjpa-custom-repo

Есть много подобных вопросов, но ни один из них не решен для меня.Возможно, это проблема Spring в текущей версии 2.1.1, или я пропустил некоторые настройки.

Ответы [ 9 ]

0 голосов
/ 29 декабря 2018

Прежде чем запустить тест, давайте удостоверимся, что основное приложение работает.На самом деле, у него есть некоторые проблемы.

1.IllegalArgumentException: Неуправляемый тип: класс com.example.demo.entity.Student.

Проблема: @EntityScan("com.example.demo.entity.*").Имя пакета неверно, поэтому класс Student не сканируется.

Решение: @EntityScan("com.example.demo.entity").

2.PropertyReferenceException: свойство attributeContainsText не найдено для типа Student!

Проблема в том, что базовый класс хранилища не установлен , и JpaQueryLookupStrategy считает, что он должен создатьRepositoryQuery из названия метода findByAttributeContainsText.Он распознает шаблон findBy{EntityPropertyName} и не может найти поле attributeContainsText в Student.

Базовый класс хранилища не задан, поскольку конфигурация StudentJPAH2Config не применяется.Конфигурация не применяется, если она не может быть сканирована.@ComponentScan("com.example.demo.dao") не сканирует пакет, в котором находится StudentJPAH2Config.

Решение - @ComponentScan("com.example.demo"), которое будет сканировать пакеты "com.example.demo" и "com.example.demo.dao" 1 .

Теперь, когда приложение в порядке, давайтевернитесь к тесту.

3.NoSuchBeanDefinitionException: нет доступных компонентов типа com.example.demo.dao.ExtendedStudentRepository.

Проблема в том, что StudentJPAH2Config не составляет всю конфигурацию , а некоторые компоненты отсутствуют.

Решение состоит в том, чтобы перечислить все классы конфигурации.

@ContextConfiguration(classes = { StudentJPAH2Config.class, DemoApplication.class })

или

@ContextConfiguration(classes = DemoApplication.class)

или

@SpringBootTest

4.JpaSystemException: Нет конструктора по умолчанию для сущности com.example.demo.entity.Student.

Проблема в том, что Hibernate 2 требует конструктор по умолчанию для Student:

@Entity
public class Student {

    @Id
    private long id;
    private String name;

    public Student() {}

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    // getters & setters

}

1 @ComponentScan("com.example.demo.dao") является избыточным, поскольку этот пакет будет сканироваться из-за наличия @SpringBootApplication.
2 Hibernate является поставщиком JPA по умолчанию в приложениях Spring.

0 голосов
/ 29 декабря 2018

Чтобы ваш тест работал, вы должны сделать следующее:

1) Заменить неправильное определение basePackages в StudentJPAH2Config на com.example.demo.dao или лучше удалить его как избыточный:

@Configuration
@EnableJpaRepositories(repositoryBaseClass = ExtendedRepositoryImpl.class)
public class StudentJPAH2Config {
}

2) Также замените basePackages в @ComponentScan и @EntityScan в DemoApplication классе на com.example.demo.dao и com.example.demo.entity.Или лучше убрать эти и @EnableTransactionManagement аннотации вообще:

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

3) Добавить конструктор без аргументов к сущности Student.

4)Исправьте ваш тестовый класс - используйте @ DataJpaTest , чтобы протестировать слой DAO и импортировать вашу StudentJPAH2Config конфигурацию:

@RunWith(SpringRunner.class)
@DataJpaTest
@Import(StudentJPAH2Config.class)
public class ExtendedStudentRepositoryIntegrationTest {
   //...
}

С этими исправлениями я успешно выполнил ваш тест.

0 голосов
/ 29 декабря 2018

Ваша реализация пользовательского базового класса репозитория Spring Data JPA работает.Было несколько пунктов с контекстом приложения Spring Boot, которые нужно было решить.У вас действительно были модули Spring Boot Starter, объявленные как зависимости, поэтому я отправил запрос pull с изменениями, которые переместили всю ответственность за ручную настройку контекста на поставщиков фабрики Spring Auto Configuration.

некоторые замечания об изменениях, которые требовались для прохождения тестов, а также некоторые краткие сведения о каждом из них.Обратите внимание, что для запуска Spring Boot Application за пределами тестовой области вам нужно добавить в classpath соответствующую зависимость поставщика JDBC вместе со всеми свойствами приложения Spring для определения свойств источника данных.Spring Auto Config должен позаботиться о любых EntityManager и TransactionManager с разумными настройками после определения свойств источника данных.См. Возможности Spring Boot - Работа с базами данных SQL .

Примечания об изменениях:

  • Удалены все аннотации Spring Configuration (за исключением @SpringBootApplication и * 1013).*).Приложение настроено так, чтобы зависеть от модулей Spring Boot Starter, которые предоставляют классы Spring Auto Configuration уже через spring.factories, а также обеспечивают соблюдение всех других зависимостей.
  • @EnableJpaRepositories не нужно объявлять basePackages как AutoМодули конфигурации по умолчанию будут использовать все пакеты ниже класса основного приложения Spring.Объявление дополнительного repositoryBaseClass все еще необходимо.
  • @ComponentScan удалено, так как модули Auto Config выполнят ComponentScan для всех пакетов ниже класса Spring Main Application, который уже находится в пакете верхнего уровня для проекта.,Кроме того, это объявляет basePackages для значения сканирования, которое не будет включать @Configuration class StudentJPAH2Config.
  • @EntityScan, так как модули Auto Config будут выполнять сканирование во всех пакетах под Spring MainКласс приложения.
  • @EnableTransactionManagement удален, так как модули Auto Config будут выполнять то же действие.
  • Удалено значение по умолчанию application.properties, поскольку они зависят от H2, однако pom обеспечивает эту зависимость только в пределахпуть к классу тестовой области.Кроме того, все свойства конфигурации, заданные в файле свойств, обычно автоматически конфигурируются Spring Starters при наличии H2.
  • Добавлен конструктор по умолчанию в Student для режима гибернации.Hibernate требует этот конструктор при управлении объектами, если только не используется @PersistenceConstructor или @Immutable, что выходит за рамки этой проблемы.
  • Настроенная автоматическая конфигурация Spring Boot для контекста приложения модульного теста в ExtendedStudentRepositoryIntegrationTest.Это то же самое, что конфигурация контекста, определенная для интеграционного теста Spring Boot в DemoApplicationTests.При использовании @ContextConfiguration напрямую с StudentJPAH2Config конфигурация, которая была определена в классе основного приложения Spring Boot (который был ComponentScan, EntityScan, TransactionManagement), не применялась к контексту приложения Spring Test.

Несколько замечаний о Spring Auto Configuration, поскольку это была основная проблема, препятствующая успешной работе этого проекта:

Средства запуска приложений Spring (как правило) делятся на два типа зависимостей.

  • starter модулей (как правило) не предоставляют много / никаких классов.Их цель - предоставить POM, которые объявляют зависимости, необходимые для хороших базовых уровней разработки для конкретного проекта Spring.Модули запуска также зависят от применимых модулей autoconfigure, которые в сочетании с этими зависимостями позволяют быстро запускать приложение.

В большинстве случаев при использовании Spring Starters основноеДрайвер не должен выяснять, что вам нужно настраивать вручную в контексте Spring, а, скорее, то, что вы должны де-конфигурировать в случае, если его базовый уровень не соответствует вашим потребностям.Когда вам нужно следовать таким урокам / примерам в Интернете, имейте в виду, что могут отображаться некоторые элементы, относящиеся к конфигурации.Иногда эти инструкции по настройке могут быть необходимы, но часто они показывают подробности для конфигурации, требуемой в не загрузочных приложениях Spring или для прозрачности.

0 голосов
/ 29 декабря 2018

Вы должны удалить @ContextConfiguration(classes = { StudentJPAH2Config.class }) и добавить @SpringBootTest аннотации к вашему тестовому классу ExtendedStudentRepositoryIntegrationTest, чтобы устранить ошибку NoSuchBeanDefinitionException, которая у вас есть в настоящее время.

Но снова у меня появляется ошибка типа:

Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.example.demo.entity.Student

, потому что Spring не может сканировать Entity Student.

. Для этого вам нужно изменить @EntityScan("com.example.demo.entity.*") на @EntityScan("com.example.demo.entity") в DemoApplication классе.

Снова я получил ошибку:

Caused by: org.springframework.data.mapping.PropertyReferenceException: No property attributeContainsText found for type Student!

Это потому, что метод findByAttributeContainsText() не является допустимым методом.

0 голосов
/ 29 декабря 2018

Были внесены следующие изменения:

@SpringBootApplication
@ComponentScan("com.example.demo.dao")
@EntityScan("com.example.demo.entity")
@EnableJpaRepositories(basePackages = "com.example.demo.dao",
        repositoryBaseClass = ExtendedRepositoryImpl.class)
@EnableTransactionManagement
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }


}

и для класса StudentJPAH2Config

@Configuration
@ComponentScan("com.example.demo")
@EnableJpaRepositories(basePackages = "com.example.demo.dao",
        repositoryBaseClass = ExtendedRepositoryImpl.class)
public class StudentJPAH2Config {
    // additional JPA Configuration
}

Класс ученика, в котором отсутствовал пустой конструктор:

@Entity
public class Student {

    public Student() {
    }

    public Student(long id, String name) {
        this.id = id;
        this.name = name;
    }

    @Id
    private long id;
    private String name;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

И результат

enter image description here

и рабочее состояние приложения

enter image description here

0 голосов
/ 28 декабря 2018

Вы должны поместить аннотацию @Primary в класс ExtendedRepositoryImpl.Это должно сработать.

Spring в основном не может определить зависимость.@Primary будет проверять, где бы вы ни вводили зависимость для ExtendedRepository, первый квалифицирующий компонент (класс) интерфейса будет ExtendedRepositoryImpl.

0 голосов
/ 28 декабря 2018

Для устранения этой проблемы необходимо внести следующие изменения.Кроме того, я выполнил это с JDK 8, поскольку у меня нет JDK 11 в моем местном.Кроме того, я выполнил ExtendedStudentRepositoryIntegrationTest.java с целью воспроизведения проблемы.

  1. В StudentJPAH2Config.java необходимо добавить компонентное сканирование.
@Configuration
@ComponentScan("com.example.demo")
@EnableJpaRepositories(basePackages = "com.example.demo.dao", 
  repositoryBaseClass = ExtendedRepositoryImpl.class)
public class StudentJPAH2Config {
В DemoApplication необходимо исправить имя базового пакета.
@SpringBootApplication
@ComponentScan("com.example.demo.dao")
@EntityScan("com.example.demo.entity")
@EnableTransactionManagement
public class DemoApplication {

Причина изменения № 1 - отсутствие сканирования компонентов в конфигурации теста, пружина не смоглаискать зависимости в правильных пакетах.# 2 необходим, поскольку ваш Student.java находится внутри пакета com.example.demo.entity напрямую, а не в любом его подпакете.Вы также можете указать @EntityScan в тестовом конфигурационном файле StudentJPAH2Config, хотя это и не нужно.

Теперь, это решит неотложную проблему, с которой вы столкнулись, но все же вы будете встречены с некоторыми другими проблемами, которые довольно просты, и вы сможете продвинуться отсюда.

0 голосов
/ 25 декабря 2018

я думаю, что вы забыли аннотировать ExtendedStudentRepository боб

package com.example.demo.dao;

import com.example.demo.entity.Student;
@Repository
public interface ExtendedStudentRepository extends ExtendedRepository<Student, Long> {
}
0 голосов
/ 25 декабря 2018

Вам нужна аннотация в вашем реализованном классе.Вы должны добавить аннотацию @Component или @Service, чтобы Spring мог принять инъекцию

@Component
public class ExtendedRepositoryImpl<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID> implements ExtendedRepository<T, ID> {
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...