Hibernate: Laden von bidirektionalen Beziehungen erzeugt mehrere SELECT Anweisungen?

DarthShader

Erfahrenes Mitglied
Hallo,

ich habe eine Frage zu dem Verhalten von Hibernate, wenn es um eine bidirektionale Verbindung zwischen zwei Tabellen bzw. Objekten geht.


Ich habe eine Klasse, welche via Hibernate Annotations eine bidirektionale Beziehung definiert, etwa so:

Java:
@Table( name = "einsatz" )
public class Einsatz
{
	// ...
	
	@Id
	@GeneratedValue( strategy = GenerationType.IDENTITY )
	private Integer	id;

	@OneToOne( mappedBy = "einsatz", cascade = CascadeType.ALL )
	private Fahrtdaten					fahrtdaten;
	
	// ...
}


Die Klasse Fahrtdaten sieht entsprechend so aus:


Java:
@Table( name = "fahrtdaten" )
public class Fahrtdaten
{
	// ...

	@Id
	@GeneratedValue( strategy = GenerationType.IDENTITY )
	private Integer	id;

	@OneToOne( optional = true )
	@JoinColumn( name = "einsatz_id" )
	private Einsatz	einsatz;

	// ...
}


Ich habe das "@OneToOne( mappedBy = "einsatz"..." in der Klasse "Einsatz", um vom Einsatz-Objekt zum Child-Objekt "Fahrtdaten" in Java navigieren zu können. In dem DB-Schema hat die Tabelle "fahrtdaten" eine Spalte "einsatz_id", was ein Foreign Key auf "einsatz.id" ist.


Nun ist es so, dass wenn ich solch ein Objekt mit Hibernate laden will

Java:
Einsatz einsatz = (Einsatz)session.get( Einsatz.class, 1 );

dann sehe ich in der SQL select Anweisung, dass er auch gleich auf "fahrtdaten" zugreift, auch, wenn die Tabelle "fahrtdaten" leer ist.

Mich stellen sich nun folgende drei Fragen:


1. Ist es normal, dass Hibernate bei bidirektionalen Beziehungen auch sofort diese entsprechend referenzierten Objekte lädt? Ich hätte intuitiv jetzt erwartet, dass Hibernate beim Laden von "Einsatz" die Tabelle "fahrtdaten" links liegen lässt. Aber anscheinend ist ihm das ja wichtig?

Ich bin deshalb irritiert, weil meine Klasse viel mehr bidirektionale Beziehungen aufweist. So viele, dass Hibernate anscheinend mehrere SELECT Anweisungen absetzt:

2. Ich lade 1 "Einsatz" und Hibernate macht 4 SELECT Anweisungen, ist das normal?

3. Und als letzte Frage: ich habe auch noch "@OneToMany( mappedBy = "einsatz" )" Member in der Klasse "Einsatz", diese lädt Hibernate anscheinend aber nicht gleich mit. Wieso?


Über Eure Hilfe würde ich mich sehr freuen


Vielen Dank!
 
Ich würde wirklich gerne mal von jemanden hören, ob diese extrem großen Select-Anweisungen normal sind. Die Domain Klasse, die ich verwende, ist zwar auc recht groß, aber das was Hibernate da an SELECT SQL generiert, überrascht mich doch sehr - das ist _seitenweise_ SQL nur um ein "Einsatz" Objekt aus der DB zu holen, ich verstehe aber nicht genau, warum :-/
 
1. Ist es normal, dass Hibernate bei bidirektionalen Beziehungen auch sofort diese entsprechend referenzierten Objekte lädt? Ich hätte intuitiv jetzt erwartet, dass Hibernate beim Laden von "Einsatz" die Tabelle "fahrtdaten" links liegen lässt. Aber anscheinend ist ihm das ja wichtig?

Ich bin deshalb irritiert, weil meine Klasse viel mehr bidirektionale Beziehungen aufweist. So viele, dass Hibernate anscheinend mehrere SELECT Anweisungen absetzt:

OneToOne beziehungen werden per default eager geladen. Ich bezweifle allerdings, dass diese Beziehung die vielen selects auslöst. Schau mal in die Folien vom Michael Plöd (http://www.java-forum-stuttgart.de/abstracts.html#E7) ich vermute du läufst in ein N+1-SELECTS-Problem... JDBC Batchsize setzen sollte da abhilfe schaffen...

REINHAUN!
 
1. Ist es normal, dass Hibernate bei bidirektionalen Beziehungen auch sofort diese entsprechend referenzierten Objekte lädt? Ich hätte intuitiv jetzt erwartet, dass Hibernate beim Laden von "Einsatz" die Tabelle "fahrtdaten" links liegen lässt. Aber anscheinend ist ihm das ja wichtig?

Ich bin deshalb irritiert, weil meine Klasse viel mehr bidirektionale Beziehungen aufweist. So viele, dass Hibernate anscheinend mehrere SELECT Anweisungen absetzt:
Bei OneToOne Beziehungen ist der default fetchType = EAGER

2. Ich lade 1 "Einsatz" und Hibernate macht 4 SELECT Anweisungen, ist das normal?
Dazu müsste man sehen ob noch mehr Entitäten in einer Beziehung zu Einsatz stehen, wie z.B. Member.

3. Und als letzte Frage: ich habe auch noch "@OneToMany( mappedBy = "einsatz" )" Member in der Klasse "Einsatz", diese lädt Hibernate anscheinend aber nicht gleich mit. Wieso?
Bei OneToMany Beziehungen ist der default fetchType = LAZY

FetchType:
Der fetchType EAGER steht für das automatische mitladen des Bezugsobjektes, wohingegen LAZY die Beziehung nicht mit läd. Der FetchType ist ein Attribut der Beziehungsannotation (@OneToOne, @OneToMany) und wird somit innerhalb dieser gesetzt.
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück