Избегайте ненужного запроса SQL select при получении прокси-сервера объекта с использованием entityManager.getReference () с данными hibernate и spring jpa - PullRequest
0 голосов
/ 08 мая 2020

Я борюсь с ненужным запросом SQL select при попытке получить ссылку на объект с помощью репозитория данных Spring с использованием Hibernate в качестве поставщика сохраняемости. Мой случай касается много раз обсуждаемого вопроса об использовании entityManager.getReference() для получения прокси-объекта с только что инициализированным id значением здесь и здесь . Но это не работает, как описано.

У меня следующая среда и код

  1. Проект Spring Boot JPA с Hibernate
  2. Один мертвый простой объект Foo
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "d20_foo")
public class Foo {

    @Id
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

В моем служебном коде я просто вызываю getReference точно так же

@Service
@Transactional
public class MyService {

@PersistenceContext
private EntityManager entityManager;

...
public void getFooLink() {
...
    Foo foo = entityManager.getReference(Foo.class,1L);
...
}
...

}

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

Hibernate: 
    select
        foo0_.id as id1_0_0_,
        foo0_.name as name2_0_0_ 
    from
        d20_foo foo0_ 
    where
        foo0_.id=?

Почему? Почему запрос выполняется вместо того, чтобы просто возвращать прокси-объект?

Я не использовал никаких дополнительных полей (например, вызов getName () для возвращаемого объекта) и сделал все, как описано в справочных реализациях.

Мне не нужен дополнительный запрос - Foo сущность является объектом только для чтения, и мне она нужна как объект, на который ссылается другая сущность.

Ответы [ 2 ]

0 голосов
/ 23 августа 2020

Вы пытались вместо этого объявлять аннотацию JPA для методов получения?

@Entity
@Table(name = "d20_foo")
public class Foo {

    
    private Long id;
    private String name;

    @Id
    @Column(name = "id")
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "name")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
0 голосов
/ 09 мая 2020

Наконец, я думаю, ответ был прост.

Это был режим отладки (возможно, особенно в IntelliJ IDEA) , который обманул меня и показал такие журналы. Когда я попытался отслеживать этот код без отладки (просто записывая логи в консоль) - все в порядке. Возможно, когда я выполняю отладку, моя IDE вызывает некоторые аксессоры свойств (возможно, поля name), которые заставляют Hibernate выполнять запросы выбора для инициализации прокси.

Итак, наконец, все работает как ожидалось

...