# JSF Designfrage bzgl. DB-Zugriff



## Marsman (7. Apr 2008)

Hallo Ihr!

Ich möchte in meiner Anzeige die Daten bei jedem Laden neu ermitteln. Also nicht nur einmal beim Instanzieren der Session, sondern auch, wenn zum Beispiel im Browser F5 gedrückt wird. Weil dabei auf die Datenbank zugegriffen wird, soll das je Aktualsierung der Anzeige aber auch nur genau einmal passieren. Dazu habe ich in meiner Bean folgenden Code:


```
public List<Model> getList() {
	// Liste nur laden, wenn für die Anzeige aktuelle Daten benötigt werden
	if (FacesContext.getCurrentInstance().getRenderResponse()) {
		Transaction tx = getSession().beginTransaction();
		List<Model> data = myDAO.findAll();
		tx.commit();
	}
	return data;
}
```

In der JSF-Seite habe ich nun eine datatable, die die Daten anzeigt. Außerdem soll der Benutzer darüber informiert werden, wenn die Liste gar keine Daten enthält. Dazu habe ich im Footer eine entsprechende Abfrage programmiert:


```
<h:dataTable var="row" value"#{myBean.list}>
  <h:column>
    ...
  </h:column>
  <f:facet name="footer">
    <h:outputText rendered="#{empty myBean.list} value="Keine Einträge in der Liste." />
  </f:facet>
</h:dataTable>
```

Mein Problem ist nun, dass der Zugriff auf die Daten bei jeder Anzeige doch zweimal erfolgt. Und zwar einmal wegen der EL "empty...." im Footer. Und einmal wegen Anzeige der dataTable selbst.

Vielleicht sehe ich es auch einfach nicht. Aber ich frage mich, wie och dieses Problem vernünftig lösen kann. Ich würde mich freuen, wenn mir jemand mit JSF-Erfahrung dazu was schreiben könnte. 

Titus


----------



## Marsman (10. Apr 2008)

Hallo Ihr!

Ich hatte vor ein paar Tage, die Frage zu meinem Strukturproblem gestellt (siehe oben). Leider habe ich noch immer keine wirklich sinnvolle Lösung und hier auch nix mehr gelesen. War die Frage zu schwer? Oder zu leicht? Oder zu blöd?  :? 

Titus


----------



## maki (10. Apr 2008)

Wenn du in getList jedesmal eine DB Abfrage machst, wird jedesmal eine DB Abfrage ausgeführt, wenn du getList() aufrufst 

Muss denn wirklich in getList jedesmal eine DB Abfrage ausgeführt werden?

Dein Versuch das mit getRenderResponse() zu lösen wirkt sehr schräg imho.

Wann müssen denn die Daten geladen werden?
Wahrscheinlich nur einmal, oder?


----------



## SnooP (10. Apr 2008)

Wenn die Daten nicht zu groß sind, kannst du sie in der Session speichern, sprich der managed-bean... und den getter lazy bauen:
if (data == null) mache db-abfrage; return data;
Falls sie groß sind... entweder manuell cachen über das zugrundeliegende DAO z.B. in einer hashmap oder ähnliches... - der zugriff des daos ist dann ebenfalls lazy.
Oder du benutzt einen Standardmechanismus von Hibernate, wie etwa den ehcache.

Allerdings ist vermutlich erstmal die erste Variante interessanter für dich... was das RenderResponse soll, weiß ich auch nich...


----------



## maki (10. Apr 2008)

Session Scope ist nicht immer richtig, zB. wenn die Daten welche geladen werden, durch diese Transaktion geändert würden, würde man immer noch die alten, "verfallenen" Daten anzeigen


----------



## robertpic71 (10. Apr 2008)

Marsman hat gesagt.:
			
		

> Ich würde mich freuen, wenn mir jemand mit JSF-Erfahrung dazu was schreiben könnte.



Ich habe nur wenig JSF-Erfahrung (ich habs nur evaluiert und für zu unproduktiv für unser Umfeld befunden), aber trotzdem mein Vorschlag:


```
private boolean listEmpty;
...
public List<Model> getList() {
   // Liste nur laden, wenn für die Anzeige aktuelle Daten benötigt werden
   if (FacesContext.getCurrentInstance().getRenderResponse()) {
      Transaction tx = getSession().beginTransaction();
      List<Model> data = myDAO.findAll();
      listEmpty = data.isEmpty();      // <<<<< neu
      tx.commit();
   }
   return data;
} 
public boolean isListEmpty() {
   return listEmpty;
}

in der GUI:
<h:outputText rendered="#{myBean.listEmpty}" value="Keine Einträge in der Liste." />
```

/Robert


----------



## Marsman (10. Apr 2008)

Erstmal Danke für die vielen Antworten.

@snoop: Weil ich für die Bean Session-Scope verwende, würden die Daten beim lazy loading nur einmal bei der Instanzierung der Bean geladen werden. Wenn der User F5 drückt oder einen Datensatz über eine weiteren Page ändert, leider nicht.

@maki: Request-Scope würde das Problem zwar lösen. Allerdings hatte ich dann immer Probleme bei der Kommunikation zwischen den Beans. Wenn ich zum Beispiel aus einer anderen Bean (Page) komme und Daten auf folgende Weise übergebe, klappt das nicht, weil bei Request-Scope immer eine zweite Instanz der Bean erzeugt wurde und die Daten dort nicht ankamen:


```
public String showTable() {
  MyBean myBean = (NextBean) fc.getApplication().createValueBinding("#{myBean}").getValue(fc);
  myBean.setDiesUndDas(...);
  return "gotoMyBean"
}
```

@robertpic71: Leider ist nicht festgelegt, in welcher Reihenfolge JSF die Properties der Page abruft. Wird also die Property listEmpty vor list abgerufen, ist die Liste noch gar nicht geladen und würde null liefern, obwohl die Liste evtl. Daten haben würde. Und umgekehrt.

Alle drei Varianten habe ich schon probiert und brachten mich bisher nicht richtig weiter. Vielleicht bin ich ja auch generell auf dem Holzweg. Letztlich geht es darum, eine einfache Datenverwaltung bestehend aus einer Liste der Daten und weiteren Pages zum Hinzufügen, ändern und Löschen von Sätzen aufzubauen. Vielleicht doch noch jemand den entscheidenden Hinweis? :idea: 


Titus


----------



## maki (10. Apr 2008)

IMHO ist dein Ablauf falsch.

Die Liste beim aufruf von getList() zu füllen ist daneben, muss vorher passieren, in einer Art Initialisierungsmethode.

Nebenbei, ich glaube kaum das man nur mit JSF weit kommt, man braucht weitere Frameworks.


----------



## Marsman (11. Apr 2008)

maki hat gesagt.:
			
		

> IMHO ist dein Ablauf falsch. Die Liste beim aufruf von getList() zu füllen ist daneben, muss vorher passieren, in einer Art Initialisierungsmethode.



Das habe ich auch schon oft gesehen und mein Code entsprechend umgestellt.



> Nebenbei, ich glaube kaum das man nur mit JSF weit kommt, man braucht weitere Frameworks.



Welche würdest Du empfehlen? Seam, Spring?

Titus


----------



## maki (11. Apr 2008)

Wir haben hier unser eigenes, selbstgestricktes, oder besser geerbtes Framwork.
Würde persönlich aber viel lieber zu shale wechseln, es sieht vielversprechend aus imho.


----------

