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

Как лениво загружать свойства сущностей с помощью режима гибернации

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

Один из моих читателей наткнулся на сообщение о сопоставлении JSON и спросил меня, можем ли мы лениво получить свойства JSON. Этот пост демонстрирует, как легко это можно сделать при использовании Hibernate в качестве поставщика JPA.

Как я уже объяснял ранее, НЕТЕРПЕЛИВАЯ выборка-это запах кода, и нетерпеливая загрузка ассоциаций очень вредит производительности приложения. Однако мы должны быть осторожны не только с ассоциациями. Базовые свойства сущности также могут вызывать проблемы с производительностью. В этом посте я собираюсь показать вам, как вы можете лениво извлекать свойства сущностей.

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

Чтобы расширить возможности загрузки объектов с помощью базового свойства “Ленивая загрузка”, свойство включить ленивую инициализацию конфигурации должно быть явно установлено в true :


    org.hibernate.orm.tooling
    hibernate-enhance-maven-plugin
    ${hibernate.version}
    
        
            
                true
            
            
                enhance
            
        
    

Я собираюсь повторно использовать ту же модель домена, которая использовалась в сообщении о сопоставлении JSON . В принципе, мы хотим лениво извлекать все свойства JSON, потому что размер объекта JSON может быть довольно большим.

Объект Событие имеет свойство местоположение , в котором хранится объект JSON. Чтобы загрузить его лениво, нам нужно пометить это свойство аннотацией @Basic(fetch.LAZY) :

@Entity(name = "Event")
@Table(name = "event")
public class Event extends BaseEntity {

    @Type(type = "jsonb")
    @Column(columnDefinition = "jsonb")
    @Basic(fetch = FetchType.LAZY)
    private Location location;

    public Location getLocation() {
        return location;
    }

    public void setLocation(Location location) {
        this.location = location;
    }
}

Объект Участник имеет свойство билет , в котором хранится объект JSON, поэтому это свойство также аннотируется с помощью @Basic(fetch.LAZY) :

@Entity(name = "Participant")
@Table(name = "participant")
public class Participant extends BaseEntity {

    @Type(type = "jsonb")
    @Column(columnDefinition = "jsonb")
    @Basic(fetch = FetchType.LAZY)
    private Ticket ticket;

    @ManyToOne(fetch = FetchType.LAZY)
    private Event event;

    public Ticket getTicket() {
        return ticket;
    }

    public void setTicket(Ticket ticket) {
        this.ticket = ticket;
    }

    public Event getEvent() {
        return event;
    }

    public void setEvent(Event event) {
        this.event = event;
    }
}

Чтобы доказать, что ленивая загрузка свойств работает, мы собираемся извлечь объект Событие и перейти к свойству местоположение следующим образом:

Event event = entityManager.find(Event.class, 
    eventHolder.get().getId());

LOGGER.debug("Fetched event");
assertEquals("Cluj-Napoca", event.getLocation().getCity());

При запуске приведенного выше тестового случая Hibernate генерирует следующие инструкции:

SELECT e.id AS id1_0_0_
FROM   event e
WHERE  e.id = 1

-- Fetched event

SELECT e.location AS location2_0_
FROM   event e
WHERE  e.id = 1

Как вы можете видеть, первый запрос не извлекает свойство location, которое инициализируется только при первом переходе.

То же самое относится и к нашему Участнику юридическому лицу:

Participant participant = entityManager.find(Participant.class, 
    participantHolder.get().getId());

LOGGER.debug("Fetched participant");
assertEquals("ABC123", participant.getTicket().getRegistrationCode());

Спящий режим, генерирующий следующие инструкции SQL:

SELECT p.id AS id1_1_0_ ,
       p.event_id AS event_id3_1_0_
FROM   participant p
WHERE  p.id = 1

-- Fetched participant

SELECT p.ticket AS ticket2_1_
FROM   participant p
WHERE  p.id = 1

Извлечение свойств сущности лениво пригодится всякий раз, когда мы имеем дело с типами столбцов BLOB , CLOB , ДВОИЧНЫЙ , ТЕКСТ и JSON|/. По умолчанию все ленивые свойства инициализируются вместе, но это поведение можно настроить с помощью @LazyGroup , как будет объяснено в следующем посте.