Я пытаюсь повысить производительность проекта, использующего JPA.

Я использую реализацию JPA 2.1 и Hibernate 5.0.1.


Я изменил FetchType отношения ManyToOne на Lazy, так что все взорвалось.

Когда я просто пытаюсь найти все записи дочернего объекта: последняя запись содержит все пустые поля и обработчик = JavassistLazyInitializer. И это странное поведение влияет на поля, которые используют эти объекты (например, h: OneSelectMenu).

Если я удалю FetchType.Lazy, все вернется в норму.

Некоторые отпечатки:

Отладка дочернего списка 2

FetchType.Lazy

Код второго отпечатка (FetchType.Lazy):

public class Usuario implements Serializable {
  private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id_Usuario")
private Integer idUsuario;

// Fields ...

@JoinColumn(name = "Id_Tipo_Logradouro", referencedColumnName = "Id_Tipo_Logradouro", nullable = true)
@ManyToOne(optional = true, fetch = FetchType.LAZY)
private TipoLogradouro tipoLogradouro;

@JoinColumn(name = "Id_Tipo_Usuario", referencedColumnName = "Id_Tipo_Usuario")
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private TipoUsuario tipoUsuario;

@JoinColumn(name = "Id_Supervisor", referencedColumnName = "Id_Usuario")
@ManyToOne(optional = true, fetch = FetchType.LAZY)
private Usuario supervisor;

// Contructor, Getters Setters etc ...

}

public class TipoUsuario implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 1)
@Column(name = "Id_Tipo_Usuario")
private String idTipoUsuario;

@Basic(optional = false)
@NotNull
@Size(min = 1, max = 20)
@Column(name = "Descricao")
private String descricao;

@Basic(optional = false)
@NotNull
@Size(min = 1, max = 1)
@Column(name = "Possui_Supervisor")
private String possuiSupervisor;

@Size(max = 1)
@Column(name = "Possui_Meta")
private String possuiMeta;

@Size(max = 1)
@Column(name = "Recebe_Alerta")
private String recebeAlerta;

@Transient
private List<Usuario> usuarioList = new ArrayList<>();

//Contructor, Getters Setters etc ...
0
CodeinCodeout 27 Июн 2016 в 16:27
Привет, не могли бы вы добавить трассировку стека в качестве текста в вопрос? Изображения могут блокироваться и их неудобно читать / копировать.
 – 
dubes
27 Июн 2016 в 16:30
Интересно, почему вы не уволили org.hibernate.LazyInitializationException? Можете ли вы опубликовать конфигурацию гибернации и сохранения?
 – 
Youans
27 Июн 2016 в 16:45
@Dubes, хорошо! Я поменял, но первый отпечаток - это не код.
 – 
BodaoZ
27 Июн 2016 в 16:45

1 ответ

Лучший ответ

Почему

При отложенной загрузке вы даете EntityManager указание НЕ получать эти данные, если их не попросят. Итак, если в вашей транзакции вы не запрашиваете выборку этого property, вы получите только прокси для этого. Но если вы спросите у этого представителя что-либо, связанное с этим свойством, размером e.x., EntityManager получит эту информацию для вас по запросу .

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

Как это обойти

Правильный ответ зависит от вашего использования.

Если информация, которую вы в данный момент загружаете лениво, ВСЕГДА требуется, чтобы она отображалась во внешнем интерфейсе, то у вас нет никаких преимуществ делать ее ленивой загрузкой.

Иначе, если вам нужно, чтобы он отображался только тогда, когда кто-то щелкает раскрывающийся список или что-то в этом роде, вы можете заполнить эти значения на основе запроса JPA с помощью Fetch Joins.

В противном случае, если у вас есть EJB, вы можете сделать свой EntityManager расширенным.

Каждый из вариантов содержит множество деталей, но вы можете взглянуть на этот блог. сообщение от Адама Бьена для получения более подробной информации обо всех упомянутых выше вариантах и ​​многом другом!

Обновление 1 . Взгляните на этот ответ, чтобы узнать, как загрузить свойства с отложенной загрузкой. на стороне сервера.

2
Community 23 Май 2017 в 15:16
Странное поведение происходит (как показано в печати «Список дочерних отладок 2»), когда я просто вызываю «SELECT t FROM TipoUsuario t». Изолированный звонок. :(
 – 
BodaoZ
27 Июн 2016 в 22:54
1
Предполагая, что свойство - tipoUsario in t, при выполнении простого SELECT JPA не будет извлекать свойства LazyLoaded. Вы должны явно попросить JPA сделать это за вас. Попробуйте изменить запрос на следующий и дайте мне знать, как это происходит SELECT t FROM TipoUsuario t JOIN FETCH t.tipoUsuario
 – 
dubes
28 Июн 2016 в 09:53
А вот ссылка на официальную документацию для присоединения, если вам интересно. docs.oracle.com/html/E24396_01/…
 – 
dubes
28 Июн 2016 в 09:54
Спасибо за помощь, но в ТипоУсуарио сложного шрифта нет. Я отредактировал пост и включил тип TipoUsuario.
 – 
BodaoZ
28 Июн 2016 в 14:46