А где же код работы с JPA?
Одной из замечательных возможностей Spring является Spring Data JPA. Это один из «подпроектов» проекта Spring Data. По умолчанию, будем считать, что вы уже знаете, что такое JPA. Итак, нам необходимо написать обычное DAO для некоторой JPA сущности, предположим, Student.
Да, здесь следует сделать небольшую поправку. Когда речь идёт о бизнес-сущностях и JPA, то правильнее применять термин репозиторий (Repository), что мы и будем дальше делать.
На практике интерфейс обычного репозитория выглядел бы как-то так:
public interface StudentRepository { Student save(Student entity); void delete(Student entity); Optional<Student> findById(long id); List<Student> findByName(String name); // и, возможно, ещё куча методов }
А сама реализация будет выглядеть примерно таким образом:
@Repository public class StudentRepositoryImpl implements StudentRepository { @PersistenceContext private EntityManager em; @Override public Student save(Student student) { em.persist(student); } @Override public void delete(Student entity) { em.remove(employee); } @Override public Optional<Student> findById(long id) { return em.find(Person.class, id); } @Override public List<Student> findByName(String name) { // да, это неправильно, это всего лишь пример return em.createQuery("select s from Student where sname="+name) .getResultList(); } // и, возможно, ещё куча методов }
В действительности код в реальном проекте будет выглядеть немного сложнее. Появятся абстрактные Generic-репозитории, и разных специфичных методов поиска entity со сложными JPQL будет достаточно. Да и конфигурация Spring ORM + сама entity Student здесь просто опущены.
А теперь воспользуемся магией Spring Data JPA
Spring Data вводит абстракцию репозитория, поэтому CRUD-методы мы позаимствуем. Итак, наш код будет выглядеть таким образом:
import org.springframework.data.repository.CrudRepository; public interface StudentRepository extends CrudRepository<Student, Long> { List<Student> findByName(String name); // и, возможно, ещё куча методов }
Ну и чтобы этот интерфейс был найден, не забудем поставить:
@EnableJpaRepositories public class AppConfiguration { /* */ }
И… ВСЁ!
А где же код работы с JPA? Как ни странно, но кода нет! И не будет. Давайте разберёмся, как эта магия работает.
Весь SQL уже написан в entity Student с помощью аннотаций JPA. Действительно, благодаря уже настроенному маппингу этой entity на БД можно написать все методы CRUD, которые определены в интерфейсе CrudRepository.
Но как же метод findByName интерфейса StudentRepository? Несложно догадаться, что Spring Data JPA по имени метода может идентифицировать поле entity, по которому необходимо производить поиск — сгенерировать JPQL, именно тот, который был написан в первой реализации.
В действительности, методы и запросы могут быть сложнее. Приведём пример интерфейса:
public interface StudentRepository extends CrudRepository<Student, Long> { List<Student> findByName(String name); List<Student> findByNameIgnoreCase(String name); List<Student> findByNameOrEmail(String name, String email); long deleteByLastname(String lastname); // и, возможно, ещё куча методов }
В документации есть целая «таблица глаголов» для формирования более сложных действий и запросов.
Счастливого использования!
Есть вопрос? Напишите в комментариях!