- <sql:transaction>
- <sql:query>
- <sql:update>
- <sql:param>
- <sql:dateParam>
- <sql:setDataSource>
- Ein Beispiel für die Nutzung
Mit der sql-Bibliothek wurde die Möglichkeit geschaffen, direkt in JSPs einfach auf Datenbanken zuzugreifen. Das erinnert mich an alte ColdFusion-Tage, als man dies bereits mit den <cfquery>, <cfinsert>, <cfupdate>-Tags konnte. Allerdings ist es schon sehr verwunderlich, dass diese Bibliothek den Weg in die JSTL geschafft hat. Da wird einerseits (in meinen Augen völlig zurecht) immer wieder die Notwendigkeit eines sauberen Designs mit einer Trennung von Präsentationsschicht und Geschäftslogik betont, andererseits aber mit diesen Tags das direkte Durchgreifen über alle Schichtgrenzen hinweg auf die DB ermöglicht. Wir lassen dies hier einfach im Raum stehen und halten uns mit unseren üblichen Kommentaren für heute zurück. Wir beschränken uns darauf, im Folgenden alle Tags vorzustellen und überlassen es der geneigten Leserin, über Sinn oder Unsinn dieser Tags nachzudenken ;-)
| Tag | Body | Bedeutung |
| transaction | JSP | Stellt für die eingeschlossenenen SQL-Tags eine Transaktionsklammer bereit |
| query | JSP | Führt eine Datenbank-Abfrage durch (SELECT) |
| update | JSP | Führt Änderungsanfragen an die Datenbank aus (INSERT, UPDATE, DELETE) |
| param | JSP | Setzt einen Anfrageparameter auf den angegebenen Wert |
| dateParam | JSP | Setzt einen Datums- und/oder Zeitanfrageparameter auf den angegebenen Wert. Der Wert muss vom Typ java.util.Date sein |
| setdataSource | leer | Legt ein javax.sql.DataSource-Objekt in einer Variablen ab |
<sql:transaction>
| Attribut | Pflichtfeld | Bedeutung |
| dataSource | nein | Gibt die DataSource an, die verwendet werden soll. Der Wert muss entweder eine Variable vom Typ Datasource sein oder ein String, der einen JNDI-Pfad oder die JDBC-DriverManager-Parameter enthält. |
| isolation | nein | Der gewünschte Isolationslevel. Wenn dieser leer gelassen wird, ist es der standardmäßig für diese Datenquelle definierte. Mögliche Werte sind "read_uncommitted", "read_committed", "repeatable_read" und "serializable" |
Bildet eine Transaktionsklammer für <sql:query> und <sql:update>-Tags. Die möglichen Attribute sind nur nötig, wenn man mehrere Datenquellen nutzt und/oder bewusst unterschiedliche Transaktionslevel für eine Datasource nutzen will.
<sql:query>
| Attribut | Pflichtfeld | Bedeutung |
| var | ja | Der Name, unter dem das Ergebnis der SQL-Abfrage abgelegt werden soll |
| scope | nein | Der gewünschte Gültigkeitsbereich für die unter dem Attribut "var" angegebene Variable |
| dataSource | nein | Gibt die DataSource an, die verwendet werden soll. Der Wert muss entweder eine Variable vom Typ Datasource sein oder ein String, der einen JNDI-Pfad oder die JDBC-DriverManager-Parameter enthält. |
| sql | nein | Das abzusetzende Statement. Wird dieses Attribut nicht genutzt, so ist der Body des Tags für das gewünschte SQL-Statement zu nutzen |
| startRow | nein | Die erste gewünschte Zeile des Abfrageergebnisses. Für seitenweise Darstellung geeignet |
| maxRows | nein | Die maximale Anzahl der Ergebnisse, die die Abfrage liefern soll |
Dieser Tag wird für Anfragen an die Datenbank genutzt. Das Ergebnis wird in einem Objekt vom Typ javax.servlet.jsp.jstl.sql.Result abgelegt. Der Name, unter dem dieses Objekt abgelegt werden soll, bildet das einzige Pflicht-Attribut des Tags.
<sql:update>
| Attribut | Pflichtfeld | Bedeutung |
| var | nein | Der Name, unter dem das Ergebnis der SQL-Abfrage abgelegt werden soll. Das Ergebnis ist vom Typ java.lang.Integer und gibt die Anzahl der veränderten bzw. neu hinzugefügten Reihen in der veränderten Tabelle an |
| scope | nein | Der gewünschte Gültigkeitsbereich für die unter dem Attribut "var" angegebene Variable |
| dataSource | nein | Gibt die DataSource an, die verwendet werden soll. Dies muss entweder eine Variable vom Typ Datasource sein oder ein String, der einen JNDI-Pfad oder die JDBC-DriverManager-Parameter enthält. |
| sql | nein | Das abzusetzende Statement. Wird dieses Attribut nicht genutzt, so ist der Body des Tags für das gewünschte SQL-Statement zu nutzen |
Mit dem Update-Tag werden Veränderungen an der DB vorgenommen. Auch wenn der Tag <sql:update> lautet, so dient dieser Tag neben UPDATE-Statements auch für INSERT- und DELETE-Statements.
<sql:param>
| Attribut | Pflichtfeld | Bedeutung |
| value | nein | Der gewünschte Wert für den Parameter |
Die <sql:update>- und <sql:insert>-Tags können wie PreparedStatements Parameter annehmen. Dabei werden diese in der Reihenfolge in das SQL-Statement eingesetzt, in dem sie innerhalb des betreffenden Update- oder Insert-Tags vorkommen. Der gewünschte Wert kann entweder im "value"-Attribut oder im Body des Tags angegeben werden.
<sql:dateParam>
| Attribut | Pflichtfeld | Bedeutung |
| value | ja | Der gewünschte Wert für den Parameter |
| type | nein | Der Typ des Attributs. Kann "date", "time" oder "timestamp" sein |
Mit dem <sql:param>-Tag kann man dem Statement bspw. Zahlen oder String-Parameter hinzufügen. Für Datumswerte muss hingegen dieser Tag verwendet werden. Der Wert des Parameter muss – im Unterschied zum <sql:param>-Tag – zwingend im "value"-Attribut angegeben werden.
<sql:setDataSource>
| Attribut | Pflichtfeld | Bedeutung |
| var | nein | Der Name, unter dem die Datasource-Variable abgelegt werden soll. Wird dieser nicht angegeben, wird die Datenquelle unter dem Namen "javax.servlet.jsp.jstl.sql.dataSource" abgelegt |
| scope | nein | Der gewünschte Gültigkeitsbereich für die unter dem Attribut "var" angegebene DataSource |
| dataSource | nein | Gibt die DataSource an, die verwendet werden soll. Dies muss entweder eine Variable vom Typ Datasource sein oder ein String, der einen JNDI-Pfad oder die JDBC-DriverManager-Parameter enthält. |
| driver | nein | Der Name des zu verwendenden JDBC-Drivers |
| url | nein | Die URL, unter der die DB erreichbar ist |
| user | nein | Der Loginname, der für die DB-Zugriffe verwendet wird |
| password | nein | Das passende Passwort zum verwendeten Loginnamen |
Mit diesem Tag wird konfiguriert, gegen welche Datenbank und mit welchem Login die Anfragen gehen sollen. Lediglich das Attribut "dataSource" der folgenden Tabelle ist nicht selbsterklärend, weswegen wir dieses kurz erläutern. Zunächst einmal kann dieses Attribut ein Objekt vom Typ javax.sql.DataSource entgegen nehmen. Alternativ kann man einen String angeben. Dieser kann entweder ein relativer Pfad auf eine JNDI-Ressource sein oder eine kompakte Form der anderen Driver-spezifischen Attribute dieses Tags. So kann man bspw. eine PostgreSQL-Datenbank mittels des folgenden Strings als Wert des Attributs "dataSource" einbinden: jdbc:postgresql://localhost/databaseName,org.postgresql.Driver,databaseUser,databasePassword. Generell ist der Aufbau wie folgt: URL[,Treiberklasse][,DBLogin][,DB-Passwort]. D.h. lediglich die URL ist ein Pflichtfeld. alle weiteren Attribute sind je nach DB-Typ und -Konfiguration zu ergänzen.
Nutzt man den gerade beschriebenen DataSource-String oder die JDBC-relevanten Parameter, so wird ein java.sql.DriverManager-Objekt erzeugt, das keinerlei Connection-Pooling-Fähigkeiten mitbringt. Die JSTL-Spezifikation warnt daher ausdrücklich vor dieser Verwendungsart - außer für den Fall des Prototypings. Bei produktiven Anwendungen sollte immer mittels des JNDI-Pfads auf eine im Container konfigurierte DataSource zugegriffen werden. Eine solche kann man auch in reinen Servlet-Containern wie Tomcat oder Jetty konfigurieren, ein vollständiger Applikationsserver ist dazu nicht unbedingt erforderlich.
Ein Beispiel für die Nutzung
Das folgende Beispiel zeigt eine mögliche Nutzung der SQL-Tags im Zusammenspiel:
<%@page pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSTL-SQL - Example</title>
</head>
<body>
<sql:setDataSource driver="org.hsqldb.jdbcDriver"
url="jdbc:hsqldb:file:/var/hsqldb/example_db"
user="sa"
password=""
var="exampleDS"
scope="request" />
<sql:query dataSource="${exampleDS}"
var="javax_servlet_jsp_jstl_sql_Result"
maxRows="10"
startRow="0"
sql="SELECT * FROM task WHERE ID > ?">
<sql:param value="1" />
</sql:query>
<table cellspacing="0" cellpadding="0" style="border-collapse: collapse;">
<tr>
<c:forEach items="${javax_servlet_jsp_jstl_sql_Result.columnNames}" var="column">
<th style="border: 1px solid #000000; padding: 5px;">${column}</th>
</c:forEach>
</tr>
<c:forEach items="${javax_servlet_jsp_jstl_sql_Result.rows}" var="currRow">
<tr>
<c:forEach items="${javax_servlet_jsp_jstl_sql_Result.columnNames}" var="column">
<td style="border: 1px solid #000000; padding: 5px;">${currRow[column]}</td>
</c:forEach>
</tr>
</c:forEach>
</table>
</body>
</html>

