Что под капотом Spring Data JPA? | OTUS
🔥 Что нужно, чтобы писать чистый код?
Курс «Архитектура и шаблоны проектирования». Спеццена для сдавших тест!
Подробнее

Курсы

Программирование
Подготовка к сертификации Oracle Java Programmer (OCAJP)
-8%
Алгоритмы и структуры данных
-12%
Backend-разработчик на PHP
-8%
Web-разработчик на Python
-11%
Архитектура и шаблоны проектирования
-14%
JavaScript Developer. Basic Интенсив «Оптимизация в Java»
-16%
Python Developer. Professional
-13%
Разработчик Golang
-17%
iOS Developer. Professional
-13%
Scala-разработчик
-21%
Java Developer. Professional
-12%
Разработчик Node.js
-15%
React.js Developer
-12%
Android Developer. Professional
-7%
Software Architect
-12%
Программист С MS SQL Server Developer Cloud Solution Architecture Reverse-Engineering. Professional CI/CD Agile Project Manager Нереляционные базы данных Супер - интенсив по паттернам проектирования Супер-практикум по использованию и настройке GIT Symfony Framework Супер-интенсив "Tarantool"
Инфраструктура
PostgreSQL
-10%
Administrator Linux. Professional
-11%
Базы данных
-19%
Administrator Linux.Basic
-18%
Супер-интенсив «СУБД в высоконагруженных системах»
-18%
IoT-разработчик
-12%
Супер-интенсив "SQL для анализа данных"
-16%
Highload Architect
-9%
MS SQL Server Developer Безопасность Linux Cloud Solution Architecture Разработчик голосовых ассистентов и чат-ботов Внедрение и работа в DevSecOps Администратор Linux. Виртуализация и кластеризация Infrastructure as a code in Ansible Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes
Специализации Курсы в разработке Подготовительные курсы
+7 499 938-92-02

Что под капотом Spring Data JPA?

JavaDeep_22.06_Site.png

Тоже впечатлены элегантностью работы с Retrofit и Spring Data JPA? Когда вы просто добавляете в интерфейс сигнатуру метода, а при вызове этого метода оказывается, что он реально работает!

Да, долой boilerplate* code!

Так это выглядит при работе с Spring Data JPA. И никаких SQL, HQL или JPQL!

interface PersonRepository extends Repository<Person, Long> {
  List<Person> findByLastname(String lastname);
  Long countByLastname(String lastname);
}

Знаете что там внутри? Ничего нового – обычный Java Reflection API!

Когда библиотека получает ваш интерфейс, ей нужно решить два главных вопроса: 1. Как в процессе выполнения программы создать экземпляр класса, реализующий ваш интерфейс? Ведь библиотека должна дать вам возможность вызова этих методов так, как будто это методы самого обычного класса. 2. Как получить и проанализировать сигнатуры методов, которые вы описали в интерфейсе? Ведь на основании соглашений о наименовании метода интерфейса библиотеке необходимо обработать вызов этого метода определённым способом.

Класс java.lang.reflect.Proxy создан как раз для этого. Он позволяет создать динамический прокси-объект, реализующий указанный интерфейс.

В таком прокси-объекте все вызовы его методов перехватываются и направляются в специальный обработчик – реализацию интерфейса InvocationHandler.

Вот как это выглядит:

PersonRepository personRepository = (PersonRepository) Proxy.newProxyInstance(PersonRepository.class.getClassLoader(),
                new Class[] { PersonRepository.class },
                (proxy, method, args) -> {
                    String methodName = method.getName();
                    // Обрабатываем вызов метода интерфейса, возвращаем результат
                    if(methodName.startsWith("find")) {
                        // ...
                    }

                    return new Object();
                });

Лямбда-выражение (proxy, method, args) реализует интерфейс InvocationHandler и содержит логику обработки вызовов всех методов PersonRepository.

InvocationHandler содержит все необходимые для обработки вызова метаданные: – ссылку на объект, – метод которого вызвал пользователь, – сигнатуру вызванного метода с его названием, параметрами и аннотациями, – и, конечно, значения аргументов, переданных пользователем при вызове метода.

В использовании полученный прокси-объект не отличается от обыкновенного класса:

List<Person> persons = personRepository.findByLastname("Otus");

Есть вопрос? Напишите в комментариях! *Boilerplate_code

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться