360 likes | 479 Views
Play Framework, MySQL, JPA, HQL, HTML, jQuery , …. Wir bauen uns eine Webapplikation!. Unsere Webapplikation kann nach Schauspieler/innen suchen…. Unsere Webapplikation kann nach Schauspieler/inne suchen…. … und allerlei Informationen zu einem Film anzeigen.
E N D
Play Framework, MySQL, JPA, HQL, HTML, jQuery, … Wir bauen uns eine Webapplikation!
Wie funktioniert das? Analogie Bibliotheken, Zeitschriftenverleih
Wie funktioniert das? Analogie Bibliotheken, Zeitschriftenverleih Wir müssen für unsere Webapplikation programmieren: 1 – «Archivar», der die Kontrolle inne hat 2 – «Archiv», die Anbindung an die Datenbank 3 – «Kopiergerät», das sich um Darstellung kümmert
Wie funktioniert das? Analogie Bibliotheken, Zeitschriftenverleih «Controller» Archivar 1 3 2 4 «Model» Zeitschriften Archiv «View» Kopiergerät
Wie funktioniert das?Client-Server Applikationen Client Der Browser Firefox Chrome Safari Internet Explorer… Server Apache Tomcat Play Microsoft IIS … URLhttp://localhost:9000/?f=Redford Internet Die darzustellende Webseite HTML
Wie funktioniert das?Play Server: Controller: Routing Datei conf/routes # URL Methode, die ausgeführt werden soll GET / controllers.Application.actors(f ?= "") GET /actorscontrollers.Application.actors(f ?= "") GET /actorcontrollers.Application.actor(id:Long) GET /moviescontrollers.Application.movies(f ?= "") GET /moviecontrollers.Application.movie(id:Long) Mit dieser Datei teilen wir dem Play Controller mit, wer die Anfrage einer URL beantworten soll. Browser: http://localhost:9000/?f=Redford
Wie funktioniert das?Play Server: Actions Klasse controllers.Application @Transactional(readOnly = true) public static Result actors(String name) { List<Actor> actors = Actor.findActorsByName(name); // 1 return ok(views.html.actors.render(actors)); // 2 } Mit dieser Methode definieren wir, wie die Anfrage beantwortet werden soll. Eine Controller-Methode geht typischerweise zweistufig vor. Wir suchen die angeforderten Daten («Archiv»). Wir stellen die gefundenen Daten dar («Kopiergerät»). Play Server: Aufruf von Application.actors("Redford")
Wie funktioniert das?Play Server: Model Application.actors: Aufruf von Actor.findActorsByName("Redford") Klasse models.Actor Diese Klasse hat zwei Aufgaben. 1. Sie beschreibt die Tabelle «actors» in der MySQL-Datenbank. @Entity(name = "actors") // der Name der Tabelle public class Actor implements Serializable { @Id public Long actorid; // d.h. actoridistPrimärschlüssel public String name; public String sex; // … }
Wie funktioniert das?Java Persistence API Meta-Informationen im Java-Code Die sog. Annotationen wie @Entity beinhalten Informationen, die den Code beschreiben. Das Java Persistence API (JPA) ordnet Java-Klassen Tabellen in relationalen Datenbanken zu: @Entity(name = "actors") // der Name der Tabelle public class Actor implements Serializable { @Id public Long actorid; // d.h. actoridistPrimärschlüssel public String name; // d.h. esgibteineSpalte name in DB public String sex; // d.h. esgibteineSpalte sex in DB // … } Siehe auch de.wikipedia.org/wiki/Java_Persistence_API
Wie funktioniert das?Play Server: Model Aufrufvon Actor.findActorsByName("Redford") Klasse models.Actor Diese Klasse hat zwei Aufgaben. 2. Sie hat Methoden, um Daten zu suchen: @Entity(name = "actors") // der Name der Tabelle public class Actor implements Serializable { public static List<Actor> findActorsByName(String name) { if (name != null && !name.equals("")) { // Achtung, Abfrageist HQL, nicht SQL! String hql = "SELECT a FROM actors a WHERE name LIKE :name"; TypedQuery<Actor> query = JPA.em().createQuery(hql, Actor.class); query = query.setParameter("name", "%" + name + "%"); return query.getResultList(); } return new ArrayList<Actor>(); } }
Wie funktioniert das?Play Server: Model findActorsByName: Schritt für Schritt @Entity(name = "actors") // der Name der Tabelle public class Actor implements Serializable { public static List<Actor> findActorsByName(String name) { if (name != null && !name.equals("")) { // Achtung, Abfrageist HQL, nicht SQL! String hql = "SELECT a FROM actors a WHERE name LIKE :name"; TypedQuery<Actor> query = JPA.em().createQuery(hql, Actor.class); query = query.setParameter("name", "%" + name + "%"); return query.getResultList(); } return new ArrayList<Actor>(); } } WirdefinierenMethode, die einen String als Input erhält und eineListe von Actor-Objektenzurückliefert.
Wie funktioniert das?Play Server: Model findActorsByName: Schritt für Schritt @Entity(name = "actors") // der Name der Tabelle public class Actor implements Serializable { public static List<Actor> findActorsByName(String name) { if (name != null && !name.equals("")) { // Achtung, Abfrageist HQL, nicht SQL! String hql = "SELECT a FROM actors a WHERE name LIKE :name"; TypedQuery<Actor> query = JPA.em().createQuery(hql, Actor.class); query = query.setParameter("name", "%" + name + "%"); return query.getResultList(); } return new ArrayList<Actor>(); } } Falls der Input “name” vorhanden und nicht-leer ist:
Wie funktioniert das?Play Server: Model findActorsByName: Schritt für Schritt @Entity(name = "actors") // der Name der Tabelle public class Actor implements Serializable { public static List<Actor> findActorsByName(String name) { if (name != null && !name.equals("")) { // Achtung, Abfrageist HQL, nicht SQL! String hql = "SELECT a FROM actors a WHERE name LIKE :name"; TypedQuery<Actor> query = JPA.em().createQuery(hql, Actor.class); query = query.setParameter("name", "%" + name + "%"); return query.getResultList(); } return new ArrayList<Actor>(); } } WirdefinierenAbfrage. Da wir die JPA-Umsetzung Hibernate verwenden, müssenwir die Hibernate Queery Language (HQL) verwenden. Siehede.wikipedia.org/wiki/Hibernate_(Framework).
Wie funktioniert das?Play Server: Model findActorsByName: Schritt für Schritt @Entity(name = "actors") // der Name der Tabelle public class Actor implements Serializable { public static List<Actor> findActorsByName(String name) { if (name != null && !name.equals("")) { // Achtung, Abfrageist HQL, nicht SQL! String hql = "SELECT a FROM actors a WHERE name LIKE :name"; TypedQuery<Actor> query = JPA.em().createQuery(hql, Actor.class); query = query.setParameter("name", "%" + name + "%"); return query.getResultList(); } return new ArrayList<Actor>(); } } Wir bereiten die Hibernate-Anfrage vor. Wir geben mit Actor.class an, dass wir als Resultat der Anfrage eine Liste von Actor-Objekten erwarten.
Wie funktioniert das?Play Server: Model findActorsByName: Schritt für Schritt @Entity(name = "actors") // der Name der Tabelle public class Actor implements Serializable { public static List<Actor> findActorsByName(String name) { if (name != null && !name.equals("")) { // Achtung, Abfrageist HQL, nicht SQL! String hql = "SELECT a FROM actors a WHERE name LIKE :name"; TypedQuery<Actor> query = JPA.em().createQuery(hql, Actor.class); query = query.setParameter("name", "%" + name + "%"); return query.getResultList(); } return new ArrayList<Actor>(); } } Wir legen fest, dass Hibernate den Platzhalten «:name» durch den Wert ersetzen soll, der durch den Ausdruck "%" + name + "%" entsteht (in unseremBeispiel “%Redford%”.
Wie funktioniert das?Play Server: Model findActorsByName: Schritt für Schritt @Entity(name = "actors") // der Name der Tabelle public class Actor implements Serializable { public static List<Actor> findActorsByName(String name) { if (name != null && !name.equals("")) { // Achtung, Abfrageist HQL, nicht SQL! String hql = "SELECT a FROM actors a WHERE name LIKE :name"; TypedQuery<Actor> query = JPA.em().createQuery(hql, Actor.class); query = query.setParameter("name", "%" + name + "%"); return query.getResultList(); } return new ArrayList<Actor>(); } } Wir lassen Hibernate die Query ausführen. Unsere Methode liefert die Resultat-Liste von Actor-Objekten zurück, die uns Hibernate gibt.
Wie funktioniert das?Play Server: Model findActorsByName: Schritt für Schritt @Entity(name = "actors") // der Name der Tabelle public class Actor implements Serializable { public static List<Actor> findActorsByName(String name) { if (name != null && !name.equals("")) { // Achtung, Abfrageist HQL, nicht SQL! String hql = "SELECT a FROM actors a WHERE name LIKE :name"; TypedQuery<Actor> query = JPA.em().createQuery(hql, Actor.class); query = query.setParameter("name", "%" + name + "%"); return query.getResultList(); } return new ArrayList<Actor>(); } } Falls der Input “name” nichtvorhandenoder leer ist: LiefereleereListe von Actor-Objektenzurück.
Wie funktioniert das?Play Server: View Application.actors: Aufrufvon views.html.actor.render(actors) Template views/movie.scala.html Das Template gibt an, wie die Daten dargestellt werden. Teil 1: Definition der View; Formular @(actors: List[Actor]) @main(title = "IMDB-Webapplikation: Suche nach Schauspielern") { <h2>Schauspieler suchen</h2> <form> <input type="text" name="f" value="@request.queryString.getOrElse("f", Array()).mkString"> </form>
Wie funktioniert das?Play Server: View • movie.scala.html Schritt für Schritt • @(actors: List[Actor]) • @main(title = "IMDB-Webapplikation: Suche nach Schauspielern") { • <h2>Schauspieler suchen</h2> • <form> • <input type="text" name="f" • value="@request.queryString.getOrElse("f", Array()).mkString"> • </form> • Hinter dem @-Zeichen kommt jeweils ein Scala-Ausdruck. • In dieser Zeile definieren wir, dass diese View als Input die Variable «actors» erhält, die eine Liste von Actor-Objekten ist.
Wie funktioniert das?Play Server: View • movie.scala.html Schritt für Schritt • @(actors: List[Actor]) • @main(title = "IMDB-Webapplikation: Suche nach Schauspielern") { • <h2>Schauspieler suchen</h2> • <form> • <input type="text" name="f" • value="@request.queryString.getOrElse("f", Array()).mkString"> • </form> • Hier rufen wir das Template main.scala.html auf. Das Template stellt das Gerüst einer Seite dar (Header, Menü, Footer). Wir übergeben diesem Template als Inhalt der Seite alles, was zwischen den geschweiften Klammern steht.
Wie funktioniert das?Play Server: View • movie.scala.html Schritt für Schritt • @(actors: List[Actor]) • @main(title = "IMDB-Webapplikation: Suche nach Schauspielern") { • <h2>Schauspieler suchen</h2> • <form> • <input type="text" name="f" • value="@request.queryString.getOrElse("f", Array()).mkString"> • </form> • Hier definieren wir das Eingabe-Formular. «input» ist ein Eingabefeld vom Typ «text» und hat den Namen «f». Dieser Name ist wichtig: Der muss gleich sein wie in der Konfigurations-Datei routes.
Wie funktioniert das?Play Server: View Template views/movie.scala.html Teil 2: Darstellung der Daten @if(!actors.isEmpty()) { <table> <tr><th>Name</th><th>Geschlecht</th></tr> @for(actor <- actors) { <tr> <td><a href="@routes.Application.actor(actor.actorid)">@actor.name</a></td> <td>@actor.sex</td> </tr> } </table> } }
Wie funktioniert das?Play Server: View • movie.scala.html Schritt für Schritt • @if(!actors.isEmpty()) { • <table> • <tr><th>Name</th><th>Geschlecht</th></tr> • @for(actor <- actors) { • <tr> • <td><a href="@routes.Application.actor(actor.actorid)">@actor.name</a></td> • <td>@actor.sex</td> • </tr> • } • </table> • } • Falls die Liste von Actor-Objektennicht leer ist (der Benutzer also eineerfolgreicheSuchedurchgeführt hat):
Wie funktioniert das?Play Server: View • movie.scala.html Schritt für Schritt • @if(!actors.isEmpty()) { • <table> • <tr><th>Name</th><th>Geschlecht</th></tr> • @for(actor <- actors) { • <tr> • <td><a href="@routes.Application.actor(actor.actorid)">@actor.name</a></td> • <td>@actor.sex</td> • </tr> • } • </table> • } • DannzeigeeineTabelle an. ErsteZeileenthält die Spaltentitel.
Wie funktioniert das?Play Server: View • movie.scala.html Schritt für Schritt • @if(!actors.isEmpty()) { • <table> • <tr><th>Name</th><th>Geschlecht</th></tr> • @for(actor <- actors) { • <tr> • <td><a href="@routes.Application.actor(actor.actorid)">@actor.name</a></td> • <td>@actor.sex</td> • </tr> • } • </table> • } • Fülle die TabellemitweiterenZeilen: ErstelleeineTabellenzeilefürjedes Actor-Objekt in der Liste der “actors”.
Wie funktioniert das?Play Server: View • movie.scala.html Schritt für Schritt • @if(!actors.isEmpty()) { • <table> • <tr><th>Name</th><th>Geschlecht</th></tr> • @for(actor <- actors) { • <tr> • <td><a href="@routes.Application.actor(actor.actorid)">@actor.name</a></td> • <td>@actor.sex</td> • </tr> • } • </table> • } • Zeigeeinen Link auf die Detailansicht von Schauspielern an. Wirkönnen den Link von Play abfragenüberroutes.Application.actor– genauso, wiees in der Konfigurationsdatei routes definiertist.
Wie funktioniert das?Play Server: View • movie.scala.html Schritt für Schritt • @if(!actors.isEmpty()) { • <table> • <tr><th>Name</th><th>Geschlecht</th></tr> • @for(actor <- actors) { • <tr> • <td><a href="@routes.Application.actor(actor.actorid)">@actor.name</a></td> • <td>@actor.sex</td> • </tr> • } • </table> • } • Beschrifte den Link mitdemNamen des Schauspielers. Hierkönnenwireinfachalle Felder der Klasse “Actor” für die Anzeigeverwenden.
Wie funktioniert das?Play Server: View • movie.scala.html Schritt für Schritt • @if(!actors.isEmpty()) { • <table> • <tr><th>Name</th><th>Geschlecht</th></tr> • @for(actor <- actors) { • <tr> • <td><a href="@routes.Application.actor(actor.actorid)">@actor.name</a></td> • <td>@actor.sex</td> • </tr> • } • </table> • } • Zeige in der nächstenSpalte das Geschlecht des Schauspielers / der Schauspielerin an. Hierkönnenwireinfachalle Felder der Klasse “Actor” für die Anzeigeverwenden.
Wie funktioniert das?Play Server: Model-View-Controller «Controller» Application.actors 1 3 2 4 «Model» Klasse Actor «View» views/movie.scala.html
Wie funktioniert das?Struktur von Play Anwendungen Das Play Framework basiert (wie viele andere Frameworks für Web-Applikationen) auf dem Design Pattern «Model, View, Controller»bzw. auf dem verwandten Design Pattern «Front Controller». Siehe auch de.wikipedia.org/wiki/Model_View_Controller