Рубрики
Без рубрики

Прокси в режиме гибернации Метод load()

Узнайте, как работают прокси-серверы гибернации и как это влияет на метод загрузки с сущностями и их отношениями.

Автор оригинала: baeldung.

1. Обзор

В этом уроке мы увидим, что такое прокси-сервер в контексте метода Hibernate load () .

Для тех читателей, которые не знакомы с гибернацией, подумайте о том, чтобы сначала ознакомиться с основами.

2. Краткое Введение В Прокси-Серверы и Метод load()

По определению, прокси – это “функция, уполномоченная действовать в качестве заместителя или заменять другого” .

Это относится к спящему режиму, когда мы вызываем Session.load() для создания так называемого неинициализированного прокси-сервера желаемого класса сущностей.

Проще говоря, Hibernate подклассы нашего класса сущностей, используя библиотеку CGLib . Кроме метода @Id , реализация прокси делегирует все другие методы свойств сеансу гибернации для заполнения экземпляра, например:

public class HibernateProxy extends MyEntity {
    private MyEntity target;

    public String getFirstName() {
        if (target == null) {
            target = readFromDatabase();
        }
        return target.getFirstName();
    }
}

Этот подкласс будет возвращен вместо прямого запроса к базе данных.

Как только вызывается один из методов сущности, сущность загружается и в этот момент становится инициализированным прокси-сервером .

3. Прокси и ленивая загрузка

3.1. Единое Юридическое лицо

Давайте подумаем о Сотруднике как о сущности. Для начала предположим, что он не имеет никакого отношения ни к каким другим таблицам.

Если мы используем Session.load() для создания экземпляра Сотрудника :

Employee albert = session.load(Employee.class, new Long(1));

Затем Hibernate создаст неинициализированный прокси-сервер Employee . Он будет содержать идентификатор, который мы ему дали, но в противном случае не будет иметь других значений, потому что мы еще не попали в базу данных.

Однако, как только мы вызовем метод на albert :

String firstName = albert.getFirstName();

Затем Hibernate запросит таблицу базы данных employee для сущности с первичным ключом 1, заполнив albert его свойствами из соответствующей строки.

Если ему не удается найти строку, то Hibernate выдает исключение ObjectNotFoundException .

3.2. Отношения “Один ко многим”

Теперь давайте также создадим Компанию сущность, в которой Компания имеет много Сотрудников:

public class Company {
    private String name;
    private Set employees;
}

Если мы на этот раз используем Session.load() на компании:

Company bizco = session.load(Company.class, new Long(1));
String name = bizco.getName();

Затем свойства компании заполняются, как и раньше, за исключением того, что набор сотрудников немного отличается.

Видите ли, мы запросили только строку компании, но прокси-сервер оставит сотрудника в покое, пока мы не позвоним получить Сотрудников в зависимости от стратегии выборки.

3.3. Отношения “Многие к одному”

Случай похож в противоположном направлении:

public class Employee {
    private String firstName;
    private Company workplace;
}

Если мы снова используем load() :

Employee bob = session.load(Employee.class, new Long(2));
String firstName = bob.getFirstName();

боб теперь будет инициализирован, и на самом деле, рабочее место теперь будет установлен неинициализированный прокси-сервер в зависимости от стратегии выборки.

4. Ленивая загрузка

Теперь load() не всегда будет давать нам неинициализированный прокси. На самом деле, Session java doc напоминает нам (курсив добавлен):

Этот метод может возвращать проксированный экземпляр, который инициализируется по требованию при обращении к методу без идентификатора.

Простой пример того, когда это может произойти, – это размер пакета.

Допустим, мы используем @BatchSize на нашем Сотруднике объекте:

@Entity
@BatchSize(size=5)
class Employee {
    // ...
}

И на этот раз у нас трое сотрудников:

Employee catherine = session.load(Employee.class, new Long(3));
Employee darrell = session.load(Employee.class, new Long(4));
Employee emma = session.load(Employee.class, new Long(5));

Если мы вызовем getFirstName on catherine :

String cathy = catherine.getFirstName();

Затем, на самом деле, Hibernate может решить загрузить всех трех сотрудников сразу, превратив всех троих в инициализированные прокси.

А потом, когда мы позовем даррелла по имени:

String darrell = darrell.getFirstName();

Тогда Hibernate вообще не попадает в базу данных.

5. Нетерпеливая загрузка

5.1. Использование get()

Мы также можем полностью обойти прокси-серверы и попросить Hibernate загрузить реальную вещь с помощью Session.get() :

Employee finnigan = session.get(Employee.class, new Long(6));

Это вызовет базу данных сразу же, вместо того, чтобы возвращать прокси-сервер.

И на самом деле, вместо Исключение ObjectNotFoundException , он вернется нулевой если финниган не существует.

5.2. Последствия для производительности

В то время как get() удобен, load() может быть легче в базе данных.

Например, предположим, что Джеральд собирается работать в новой компании:

Employee gerald = session.get(Employee.class, new Long(7));
Company worldco = (Company) session.load(Company.class, new Long(2));
employee.setCompany(worldco);        
session.save(employee);

Поскольку мы знаем, что в этой ситуации мы собираемся изменить только запись employee , вызов load() для Компании имеет смысл.

Если бы мы позвонили получить() на Компания , тогда мы бы без необходимости загрузили все его данные из базы данных.

6. Заключение

В этой статье мы кратко узнали, как Прокси-серверы Hibernate работают и как это влияет на метод load с сущностями и их отношениями.

Кроме того, мы быстро рассмотрели, чем load() отличается от get().

Как обычно, полный исходный код, сопровождающий учебник, доступен на GitHub.