Skąd ta mania w ludziach żeby nazwy interfejsów zaczynać od I?Np. ISingleBookAdministratorService
A implementacje nazywają się normalnie. Przecież jakby się tak zastanowić to klas implementujących te interfejsy mając DI nie używasz w kodzie. Korzystasz tylko z interfejsów jako kontraktu a implementacja jest wstrzyknięta. Znacznie lepszym rozwiązaniem jest nazywanie interfejsów normalnie bez żadnych sufixów i prefixów a do implementacji dodać np. Impl na koniec.
W klasie BindingResultErrors (i nie tylko) sprawdzasz czy result nie jest nullem albo pusty itp. Proponuje zrobić jeden warunek i skorzystać np. z isBlank . Nie jest to oczywiście żaden błąd ale moim zdaniem ta metoda jest czytelniejsza, obsługuje więcej przypadków i redukuje niepotrzebny kod.
W bardzo wielu klasach zauwazyłem że pola mają dostęp default'owy. to celowe? Jak dla mnie to wszedzie powinno być prywatne.
Takie kody:
new ArrayList<String>().add("sprawdŸ czy poda³eœ odpowiednie dane")
Możesz zamienić np. na:
Arrays.asList("sprawdŸ czy poda³eœ odpowiednie dane")
@ManyToMany(fetch = FetchType.EAGER)
@Column(nullable=false)
private List<AuthorModel> authors;
Proponuję zdebugować aplikację i zobaczyć jaki muł zasysasz robiąc zapytanie np. o Książki :P
W wolnej chwili jeszcze popatrzę ale ogólnie jak na początek to moim zdaniem jest okej, trochę rzeczy do poprawy ale na juniora możesz próbować ;)