2016-06-27 21 views
0

Ich versuche, die Leistung eines Projekts, das JPA verwendet, zu verbessern.JPA. FetchType.Lazy verursacht seltsames Verhalten @ManyToOne

Ich verwende JPA 2.1 und Hibernate 5.0.1 Implementierung.

Ich änderte den FetchType einer ManyToOne-Beziehung zu Lazy, so dass das Ding in die Luft geht.

Wenn ich versuche, alle Datensätze des untergeordneten Objekts zu suchen: Der letzte Datensatz wird mit allen leeren Feldern und mit einem Handler = JavassistLazyInitializer geliefert. Und dieses seltsame Verhalten wirkt sich auf die Felder aus, die diese Objekte verwenden (wie h: OneSelectMenu).

Wenn ich die FetchType.Lazy die Sache wieder normal entfernen.

Einige Drucke:

Debug child list 2

FetchType.Lazy

-Code des zweiten Druck (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

Hallo, können Sie bitte Ihren Stacktrace als Text innerhalb der Frage hinzufügen? Bilder können blockiert werden und sind mühsam zu lesen/kopieren von. – dubes

+0

Ich frage mich, warum Sie nicht '' org.hibernate.LazyInitializationException'' gefeuert haben, können Sie die Ruhezustand und Persistenz Config – YouYou

+0

@Dubes, Ok! Ich habe mich geändert, aber der erste Druck ist kein Code. – CodeinCodeout

Antwort

1

Warum

mit Lazy Loading, Sie anweist EntityManager diese Daten nicht bekommen, wenn jemand danach fragt. Wenn Sie also in Ihrer Transaktion nicht darum bitten, dass property abgerufen wird, erhalten Sie nur einen Proxy. Aber wenn Sie fragen, dass Proxy für jede Sache im Zusammenhang mit dieser Eigenschaft, Größe für e.x., EntityManager erhalten Sie diese Informationen für Sie On-Demand.

Sieht aus wie Sie JSF für Ihre Ansicht verwenden, jetzt in diesem Fall, bevor Ihr Modell für diese Details wissen möchte das Unternehmen Manager beendet hat bereits seine Arbeit und somit nicht wissen es, diese Details erhalten hat aus die DB für dich wieder. Denken Sie daran, dass Proxies serialisiert sind. Aus Ihrer Sicht scheint Ihre Sammlung leer/leer zu sein.

Wie um diese

richtige Antwort zu erhalten, hängt von Ihrer Nutzung.

Wenn die Informationen, die Sie derzeit lazy loaded haben, IMMER im Frontend angezeigt werden müssen, haben Sie keinen Vorteil, dass sie lazy loaded werden.

Sonst, wenn Sie es nur anzeigen möchten, wenn jemand auf ein Dropdown oder etwas klickt, können Sie diese Werte basierend auf einer JPA-Abfrage mit Fetch Joins auffüllen.

Sonst, wenn Sie EJBs haben, können Sie Ihre EntityManager erweitert sehen.

Jede der Optionen hat viele Details, aber Sie können einen Blick auf diese blog post von Adam Bien für weitere Details zu allen oben genannten Optionen und mehr!

Update 1: Werfen Sie einen Blick auf diese answer, um zu sehen, wie Sie die Lazy geladenen Eigenschaften auf der Serverseite laden können.

+0

Das seltsame Verhalten auftreten (wie in Print 'Debug Kind Liste 2' gezeigt), wenn ich einfach "SELECT t FROM TipoUsuario t" aufrufen. Ein isolierter Anruf. :( – CodeinCodeout

+0

Angenommen, die Eigenschaft ist tipoUsario in t, wenn Sie eine einfache SELECT ausstellen, wird JPA die LazyLoaded-Eigenschaften nicht abrufen. Sie müssen explizit JPA bitten, dies für Sie zu tun. Versuchen Sie, die Abfrage zu ändern und lassen Sie mich wissen, wie es geht 'SELECT t VON TipoUsuario t JOIN FETCH t.tipoUsuario' – dubes

+0

und hier ist der Link zu den offiziellen Dokumenten für Join Fetch, falls Sie interessiert sind: http://docs.oracle.com/html/E24396_01/ejb3_langref.html # ejb3_langref_fetch_joins – dubes