В представленном коде можно выделить несколько ошибок и проблем:
Прочитайте код и подсчитайте ошибки
В представленном коде можно выделить несколько ошибок и проблем:
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Прочитайте код и подсчитайте ошибки
@Component
public class AuthorSearchService {
@Autowired
private AuthorRepository authorRepository;
@Autowired
private StatisticsRepository statisticsRepository;
private AlertRestClient arc = new AlertRestClient();
// В query может быть как полностью ввд, так и часть имени, например "Вадим Павло" или "павло"
@Transactional
public List<Author> search(String query) {
List<Author> authors = authorRepository.findByNameContainingIgnoreCase(query);
Statistics s = statisticsRepository.findById(query).orElse(null);
if (s == null) s = new Statistics(query);
s.setNumbers(s.getNumbers() + 1);
statisticsRepository.save(s);
if (s.getNumbers() > 1000 && authors.size() > 1000) {
System.out.println("too popular search with too much data, sending an alert...");
arc.send(query, s.getNumbers(), authors.size());
}
return authors;
}
}
@Entity
@Data
public class Author {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "author")
private List<Book> books;
public Author(String name) {
this.name = name;
}
}
Ответ
В представленном коде можно выделить несколько ошибок и проблем:
-
Отсутствие конструктора без параметров в классе Author
- В JPA сущности должен быть публичный или защищённый конструктор без параметров. В коде есть только конструктор с параметром
name.
- В JPA сущности должен быть публичный или защищённый конструктор без параметров. В коде есть только конструктор с параметром
-
Инициализация AlertRestClient вне Spring-контекста
AlertRestClient arc = new AlertRestClient();создаётся вручную, а не через DI. Лучше внедрять через@Autowiredили конструктор, чтобы использовать преимущества Spring (например, конфигурацию, мокирование).
-
Потенциальная проблема с транзакцией и чтением/записью статистики
- Метод помечен
@Transactional, что хорошо, но еслиstatisticsRepository.findById(query)возвращает null, создаётся новый объектStatistics(query), возможно, без корректной инициализации ID.
- Метод помечен
-
Использование
queryкак ID для Statistics- Если
Statisticsиспользуетqueryкак идентификатор, это должно быть явно указано в сущности. ИначеfindById(query)может не работать.
- Если
-
Отсутствие обработки исключений при отправке алерта
- Вызов
arc.send(...)может выбросить исключение, которое не обрабатывается.
- Вызов
-
Потенциальная проблема с производительностью при больших данных
- Если
authors.size()очень большой, загрузка всех авторов в память может быть неэффективной.
- Если
-
Отсутствие логгера
- Используется
System.out.println, лучше использовать логгер.
- Используется
-
Отсутствие аннотации
@NoArgsConstructorили явного конструктора без параметров в Author
Пример исправления конструктора Author:
@Entity
@Data
@NoArgsConstructor
public class Author {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "author")
private List<Book> books;
public Author(String name) {
this.name = name;
}
}
И пример внедрения AlertRestClient через DI:
@Component
public class AuthorSearchService {
@Autowired
private AuthorRepository authorRepository;
@Autowired
private StatisticsRepository statisticsRepository;
@Autowired
private AlertRestClient arc;
@Transactional
public List<Author> search(String query) {
// ...
}
}
В целом, код требует доработки для корректной работы с JPA и Spring.