# Einträge aus Datenbank einzeln darstellen (JSP, JAVA, HTML)



## Schwupsi (10. Mrz 2018)

Hallo Leute,

ich programmiere momentan für eine Webseite ein Gästebuch. Der User kann auf der Seite seinen *Namen *eingeben, einen *Betreff* und eine *Nachricht *verfassen. Mit Klicken auf den Absenden-Button werden die drei Werte über einen Controller in die Bean-Klasse übertragen, wo diese anschließend in eine Datenbank-Tabelle eingetragen werden per SQL-Statement.

Die Datenbank-Tabelle sieht so aus:

ID | Name | Betreff | Nachricht | Datum | Status

*ID* wird bei jedem Eintrag automatisch hochgezählt. *Datum *wird in einer Methode in der Bean ermittelt und zum Eintrag hinzugefügt. *Status *ist per Default auf "0" und wird auch mit einer Methode dem Eintrag hinzugefügt. Das ist später für die Freigabe der Einträge nötig (0=nicht freigegeben, 1=freigegeben).

Anschließend hole ich mir mittels Methoden die einzelnen Spalten aus der Tabelle heraus und rufe diese Methoden in der View-Klasse auf:


```
<div id="guestbookentry">
   
   
           <div id="center">
                 <jsp:getProperty property="htmlDatum" name="gb"/>
                 <jsp:getProperty property="htmlName" name="gb"/>
           </div>
           <div id="center">
                 <jsp:getProperty property="htmlBetreff" name="gb"/>
           </div>
                 <jsp:getProperty property="htmlNachricht" name="gb"/>
             
                
</div>
```

Das Problem hier ist, dass die Methoden aus der View heraus nur einmal aufgerufen werden. Ich möchte aber, dass sie die Methode solange aufruft, bis sie alle Einträge aus der DB hat.
Momentan ist es so, dass eine Ausgabe *bei einem Eintrag* in der DB so aussieht, wie ich es möchte:

                                        Eingetragen am: 09.03.18
                                        von: Max Mustermann

                                        Betreff: Nachricht 1

                                        Nachricht: blabla1

Bei *mehr als einem Eintrag* sieht die Ausgabe so aus:

                                        Eingetragen am: 09.03.18
                                                                  07.03.18
                                        von: Max Mustermann
                                                Maria Musterfrau
                                        Betreff: Nachricht 1
                                                    Nachricht2
                                        Nachricht: blabla1
                                                         blabla2

Ich müsste es irgendwie hinkriegen, dass die Ausgabe Zeile für Zeile aus der DB erfolgt und nicht alle Daten geholt werden und einfach an den String den ich returne angehängt werden.

Am besten so:
                                        Eingetragen am: 09.03.18
                                        von: Max Mustermann

                                        Betreff: Nachricht 1

                                        Nachricht: blabla1
-------------------------------------------------------------------------------------------------
                                        Eingetragen am: 07.03.18
                                        von: Maria Musterfrau

                                        Betreff: Nachricht 2

                                        Nachricht: blabla2

Den SELECT Befehl für die Nachricht z.B. müsste ich irgendwie umbauen in "SELECT nachricht FROM tabelle WHERE id = " + i;

i wäre <= Anzahl Einträge in der DB und würde dann solange hochgezählt werden.
Aber es bringt mir nichts, wenn ich die Methode nur einmal aufrufen kann.

Ich hoffe ich konnte mein Anliegen einigermaßen verständlich schildern und würde mich über Anregungen und Tipps freuen.

MfG


----------



## looparda (10. Mrz 2018)

Es ist schon ok, dass du mit einem Mal mehrere Einträge holst. Du kannst diese Einträge dann in eine Collection vom Typ deines Gästebuch-Eintrag-Beans mappen. Im JSP iterierst du über diese Collection und machst die Ausgabe.

```
<c:forEach items="${alist}" var="listItem">
    ${listItem} <br />
</c:forEach>
```
http://www.javawebtutor.com/articles/jsp/jstl-foreach-tag.php


----------



## Schwupsi (10. Mrz 2018)

looparda hat gesagt.:


> ```
> <c:forEach items="${alist}" var="listItem">
> ${listItem} <br />
> </c:forEach>
> ...



Danke dir. Wollte gerade deinen Vorschlag probieren, aber ich kriege JSTL nicht importiert. Habe es mit dem Code 
	
	
	
	





```
<%@taglib prefix="c" uri="http://java.sun.com/jstl/core_rt"%>
```
 probiert, aber er zeigt mir einen Fehler "Can not find the tag library descriptor for "http://java.sun.com/jstl/core_rt"

Wie kriege ich JSTL importiert? Muss ich diese Schritte hier ausführen?
-> https://www.tutorialspoint.com/jsp/jsp_standard_tag_library.htm


----------



## Schwupsi (10. Mrz 2018)

Update: Habe es mit JSTL hinbekommen. 
Ich verstehe aber noch nicht so ganz wie du das mit dem forEach meinst. 

Ich habe für jeden Wert, den ich darstellen möchte, eine Methode, die einen "String html" zurückliefert. 
Für die "Nachricht" habe ich zum Beispiel folgende Methode:


```
public String getHtmlNachricht () {
        String html = "";
        Vector <String> myKeys = this.nachrichtFromDB;       
        Iterator<String> iter = myKeys.iterator();   
       
        while (iter.hasNext()) {
        String mykey = iter.next();              
        html += "<h4>" + mykey + "</h4>" + "<br>";     
        }       
        return html ;       
    }
```

Für die Werte "Name", "Betreff" und "Datum" sehen die Methoden genauso aus. 
Wie kann ich das mit dem forEach Code verknüpfen?


----------



## looparda (10. Mrz 2018)

Ich wollte dir gerade ein Beispiel zusammenschreiben, aber mir ist nicht klar, was das ist:


Schwupsi hat gesagt.:


> Vector <String> myKeys = *this*.nachrichtFromDB;


Vielleicht lieferst du noch dein Datenbankschema dazu als SQL oder ERD.


----------



## looparda (10. Mrz 2018)

Ich habe das mit den keys erstmal außen vor gelassen, weil ich es nicht als nötig sehe.
Der GaestebuchController kümmert sich darum die Einträge aus der Datenbank zu holen und stellt eine Liste von Einträgen bereit.

```
interface EintragDBO {
    String getNachricht();
}

interface EintraegeRepository {
    List<EintragDBO> getAll();
}

class Eintrag {

    private String nachricht;

    public Eintrag(EintragDBO eintragDBO) {
        this.nachricht = eintragDBO.getNachricht();
    }

    public String getHtmlNachricht () {
        //TODO: escape html to prevent XSS and other attacks
        return this.nachricht;
    }

    // ... andere getter
}

class GaestebuchController {

    private List<Eintrag> eintraege;

    public GaestebuchController(EintraegeRepository eintraegeRepository) {
        this.eintraege = new ArrayList<>();
        // Datenbank-Objekte laden
        List<EintragDBO> eintragDBOs = eintraegeRepository.getAll();
        // Trennung von Datenbank-Objekten und Objekten auf denen die Applikations-Logik arbeitet.
        for (EintragDBO eintragDBO: eintragDBOs) {
            this.eintraege.add( new Eintrag( eintragDBO ));
        }
    }

    public List<Eintrag> getEintraege() {
        return eintraege;
    }

}
```
Im JSP machst du deine Darstellung wie die Daten angezeigt werden sollen. Das ist für jeden Eintrag ja das gleiche Format. Deshalb eine Schleife über alle Einträge. Nur die Daten werden im Template ausgetauscht.

```
<c:forEach items="${gaestebuchController.getEintraege()}" var="eintrag">
<h4>Eingetragen am:</h4> ${eintrag.getDatum()}
<h4>von:</h4> ${eintrag.getVon()}
<h4>Betreff:</h4> ${eintrag.getBetreff()}
<h4>Nachricht:</h4> ${eintrag.getNachricht()}
<br />
</c:forEach>
```
So ist das Prinzip - die genaue Implementierung fehlt. Vor allem beim JSP kenne ich mich nicht aus und weiß nicht wie genau man es schreibt. Aber es geht ja nur darum zu zeigen wie es ablaufen kann. Den gaestebuchController muss man ins JSP injizieren - aber das müsstest du auch schon bei deinem vorherigen Template für den einzelnen Eintrag gemacht haben.


----------



## mrBrown (11. Mrz 2018)

Wenn ich mir den Code so angucke und an das dahinterliegende Design denke, offenbart das ziemliche Lücken in den Grundlagen (und eine zum Himmel schreiende XSS-Lücke) :/


----------



## Schwupsi (12. Mrz 2018)

mrBrown hat gesagt.:


> Wenn ich mir den Code so angucke und an das dahinterliegende Design denke, offenbart das ziemliche Lücken in den Grundlagen (und eine zum Himmel schreiende XSS-Lücke) :/


Danke für den Hinweis 
Habe aber das XSS-Problem im Hinterkopf und werde das nachträglich fixen. Wollte erstmal mein Problem hier aus der Welt kriegen, mit dem Ziehen einzelner Gästebucheinträge. Aber habe es nun hinbekommen. 

Danke an *looparda *für die großartige Hilfe!


----------



## looparda (12. Mrz 2018)

Ich möchte noch anmerken, dass das Mappen von dbo -> Applikations-Modell nicht in den Controller gehört sondern eher in das Repository. Sofern man da überhaupt eine Trennung für Datenklassen und Applikations-Modell haben möchte oder je nachdem welche Architektur man hat. Und statt dem kompletten Controller in JSP zu injizieren reicht es nur die Liste der Einträge zu übergeben.

@mrBrown galt deine Antwort mir?


----------



## mrBrown (12. Mrz 2018)

looparda hat gesagt.:


> @mrBrown galt deine Antwort mir?


Nein, deins ist genau das, was man machen würde


----------

