Я пытаюсь создать 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, или я пропустил некоторую настройку.
Да. Моя другая программа также использует ту же настройку среды
Я использую OpenJDK 11
Вкалываю репо на тестирование github.com/sesong11/springjpa-custom-repo/blob/master/src/te st /…




Вам нужна аннотация в вашем реализованном классе. Вы должны добавить аннотацию @Component или @Service, чтобы Spring мог подобрать инъекцию.
@Component
public class ExtendedRepositoryImpl<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID> implements ExtendedRepository<T, ID> {
Обычно такая ошибка связана с ответом, который я вам дал, и иногда я его получаю. Пожалуйста, посмотрите официальную документацию или другие рабочие примеры в github. Страница, на которую вы ссылаетесь, не всегда дает вам полный исходный код, а дает частичные или небольшие фрагменты реализации.
Для решения этой проблемы вам необходимо внести следующие изменения. Кроме того, я выполнил это с помощью JDK 8, поскольку у меня нет JDK 11 в моем локальном хранилище. Кроме того, я выполнил ExtendedStudentRepositoryIntegrationTest.java с целью воспроизведения проблемы.
@Configuration @ComponentScan("com.example.demo") @EnableJpaRepositories(basePackages = "com.example.demo.dao", repositoryBaseClass = ExtendedRepositoryImpl.class) public class StudentJPAH2Config {
@SpringBootApplication @ComponentScan("com.example.demo.dao") @EntityScan("com.example.demo.entity") @EnableTransactionManagement public class DemoApplication {
Причина изменения №1 - отсутствие сканирования компонентов в тестовой конфигурации, Spring не смог найти зависимости в нужных пакетах. # 2 необходим, так как ваш Student.java находится внутри пакета com.example.demo.entity напрямую, а не в каком-либо его подпакете. Вы также можете указать @EntityScan в тестовом конфигурационном файле StudentJPAH2Config, но это не обязательно.
Теперь это решает сиюминутную проблему, с которой вы столкнулись, но, тем не менее, вас будут приветствовать некоторые другие проблемы, которые довольно просты, и вы сможете решить их отсюда.
Вы должны поместить аннотацию @Primary в класс ExtendedRepositoryImpl. Он должен работать.
Spring в принципе не может квалифицировать зависимость. @Primary гарантирует, что куда бы вы ни вводили зависимость для интерфейса ExtendedRepository, первым квалифицирующим bean-компонентом (классом) будет ExtendedRepositoryImpl.
Были внесены следующие изменения:
@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;
}
}
И результат
и состояние работы приложения
@DarrenForsythe Вы прочитали вопрос ?? вот вы хвастаетесь лучшими наработками ??? а вы решили проблему ??? просто внимательно прочитайте вопрос, прежде чем голосовать против.
Да, я тоже смотрел исходный код. Возможно, прочтите документацию по Spring Boot. Это не приложение Spring Framework, требующее такого уровня конфигурации, просто потому, что оно работает, еще не значит, что это правильно.
@DarrenForsythe этих конфигураций можно было бы немного избежать. Но его цель не была целью этого вопроса. Вы говорите это просто для аргументации. Придерживайтесь сути дела, чтобы помочь людям, а не просто интересно здесь и там.
Я сказал это, чтобы остановить распространение плохих конфигураций пружинных ботинок. Вы сами сказали, что их можно избежать. Так почему бы не следовать лучшим практикам? Это приложение для весенней загрузки, а не весенний фреймворк.
Вы должны удалить @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() не является допустимым.
Прежде чем запускать тест, давайте убедимся, что основное приложение запущено. Собственно, тут есть некоторые проблемы.
IllegalArgumentException: Неуправляемый тип: класс com.example.demo.entity.Student.Проблема в @EntityScan("com.example.demo.entity.*"). Имя пакета неверно, поэтому класс Student не сканируется.
Решение - @EntityScan("com.example.demo.entity").
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.
Теперь, когда с приложением все в порядке, вернемся к тесту.
NoSuchBeanDefinitionException: Нет подходящего компонента типа com.example.demo.dao.ExtendedStudentRepository.Проблема в том, что отсутствуют StudentJPAH2Config не составляет всей конфигурации и некоторые beans.
Решение состоит в том, чтобы перечислить все классы конфигурации.
@ContextConfiguration(classes = { StudentJPAH2Config.class, DemoApplication.class })
или
@ContextConfiguration(classes = DemoApplication.class)
или
@SpringBootTest
JpaSystemException: нет конструктора по умолчанию для объекта com.example.demo.entity.Student.Проблема в том, что Hibernate2 требует конструктора по умолчанию для 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") is redundant since this package will be scanned because of @SpringBootApplication located in there.
2 Hibernate is the default JPA provider in Spring applications.
Лучший ответ, который я когда-либо видел. Спасибо!
Чтобы ваш тест заработал, вам необходимо сделать следующее:
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 {
//...
}
С этими исправлениями я успешно выполнил ваш тест.
Я не могу удалить @ComponentScan и @EntityScan, это ошибка Field * in * required a bean of type * that could not be found, когда я импортирую свой пример проекта в проект с несколькими модулями. Другие проблемы с моим другим модулем должны реализовывать конфигурацию с аннотацией @EnableJpaRepositories(repositoryBaseClass = SimpleJpaRepository.class) или @EnableJpaRepositories(repositoryBaseClass = ExtendedRepositoryImpl.class), иначе это ошибка required a bean of type * that could not be found
Не могли бы вы убедиться, что у вас установлен
java11и ваша среда использует его для запуска кода?