The SQL JSTL tag library
allows us to execute SQL queries from JSP pages. As this tag library
mixes presentation and database access code, it should only be used for
prototyping and for writing simple "throwaway" applications. For more
complex applications, it is always a good idea to follow the DAO and MVC
design patterns.
The following example illustrates the most commonly used tags in the SQL JSTL tag library:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!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>SQL Tag Demo</title>
</head>
<body>
<sql:setDataSource dataSource="jdbc/__CustomerDBPool" />
<sql:transaction>
<sql:update>
insert into CUSTOMERS (CUSTOMER_ID, FIRST_NAME, LAST_NAME) values (((select max(CUSTOMER_ID) from customers) + 1), ?, ?)
<sql:param value="${param.firstName}" />
<sql:param value="${param.lastName}" />
</sql:update>
</sql:transaction>
<p>Successfully inserted the following row into the CUSTOMERS table:</p>
<sql:query var="selectedRows" sql="select FIRST_NAME, LAST_NAME from customers where FIRST_NAME = ? and LAST_NAME = ?">
<sql:param value="${param.firstName}" />
<sql:param value="${param.lastName}" />
</sql:query>
<table border="1" cellpadding="0" cellspacing="0">
<tr>
<td>First Name</td>
<td>Last Name</td>
</tr>
<c:forEach var="currentRow" items="${selectedRows.rows}">
<tr>
<td><c:out value="${currentRow.FIRST_NAME}" /></td>
<td><c:out value="${currentRow.LAST_NAME}" /></td>
</tr>
</c:forEach>
</table>
</body>
</html>
After packaging this JSP in a
WAR file, deploying the WAR file, and pointing the browser to the JSP's
URL (and passing the parameters that the page expects), we should see a
page like the following:
Like most of our examples,
the previous page is pretty simplistic and does not necessarily
represent what would be done in an actual application. The page inserts a
row into the CUSTOMERS table and then queries the table for rows
matching the values inserted. A real application (keeping in mind that
the SQL tag library should only be used for very simple applications)
would typically insert values obtained from request parameters into the
database. It would be unlikely for the same page to query the database
for the data just inserted. This would probably be done in a separate
page.
The first JSTL SQL tag we see in the example is the<sql:setDataSource>
tag. This tag sets the datasource to be used for database access. The
datasource can either be obtained via JNDI by using its JNDI name as the
value of this tag's datasource attribute, or by specifying a JDBC URL, username, and password via the url, user, and password attributes. The previous example uses the first approach. In order for this approach to work correctly, a<resource-ref> element must be added to the application's web.xml file.
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<resource-ref>
<res-ref-name>jdbc/__CustomerDBPool</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app>
The<res-ref-name> subelement of the<resource-ref>
element contains the JNDI name of a JDBC datasource. This needs to be
set up in the application server.
The<res-type> subelement of the<resource-ref> element contains the fully qualified name of the resource to be obtained via JNDI. For datasources, this will always be javax.sql.DataSource.
The<res-auth> subelement of the<resource-ref> element should have a value of Container when using the<resource-ref>
element to define a datasource as a resource. This allows the
application server to use the credentials set up in the connection pool
corresponding to the datasource to log into the database.
No suitable driver SQL exception
Sometimes, the<sql:setDataSource> tag will result in a java.sql.SQLException: No suitable driver exception when using its datasource attribute to locate the datasource via JNDI. This typically means that we forgot to modify the application's web.xml file, as described previously.
Like we mentioned before, an alternate way of using the<sql:setDataSource> tag is to specify the database connection URL and credentials. If we had used this approach in the previous example, the<sql:setDataSource> tag would have looked like this:
<sql:setDataSource url="jdbc:derby://localhost:1527/customerdb" user="dev" password="dev" />
The attributes used are self-explanatory. The url attribute should contain the JDBC URL for the connection. The user and password attributes should contain the username and password used to log into the database respectively.
The next JSTL SQL tag we see in the example is the<sql:transaction> tag. Unsurprisingly, this tag wraps any<sql:query> and<sql:update> tags it contains in a transaction.
Next, we see the<sql:update> tag that is used to execute any queries that modify the data in the database. It can be used for INSERT, UPDATE, or DELETE
SQL statements. As can be seen in the example, queries inside this tag
can have one or more parameters. Just like when using JDBC Prepared
Statements, question marks are used as placeholders for parameters. The<sql:param> tag is used to set the value of any parameter in a query defined in a<sql:update> or<sql:query> tag. The<sql:param> tag sets the value for its containing tag via its value attribute that may contain a String constant or a Unified Expression Language expression.
The<sql:query> tag is used to query data from the database via a SELECT statement. The query's result set is stored in a variable defined by this tag's var attribute. By default, the var attribute has a scope of page. This can be changed by using the<sql:query> scope attribute and setting its value to the appropriate scope (page, request, session, or application). As can be seen in the example, we can iterate through the variable defined by this tag's var attribute by using a<c:forEach> tag.
The following table lists all the JSTL SQL tags:
Tag
|
Description
|
Example
|
---|
<sql:dateParam>
|
Sets the value for a date parameter in a<sql:query> or<sql:update> tag.
|
See example for<sql:query>.
|
<sql:param>
|
Sets the value for a text or numeric parameter in a<sql:query> or<sql:update> tag.
|
See example for<sql:update>.
|
<sql:query>
|
Executes the SQL query defined in its sql attribute and optionally attaches the resulting result set into the specified scope, using the specified variable name.
|
<sql:query sql="select * from table where last_update < ?" var="selectedRows">
<sql:dateParam value= "${someDate}"/>
</sql:query>
|
<sql:setDataSource>
|
Defines the datasource to be used at the specified scope. If no scope is specified, the default scope is page. Datasource can be obtained via a JNDI lookup or by specifying a JDBC URL through the url, user, and password attributes..
|
<sql:setDataSource dataSource="jdbc/ __CustomerDBPool" />
|
<sql:transaction>
|
Wraps any<sql:query> and<sql:update> tags inside its body in a transaction.
|
<sql:transaction>
<sql:update sql="update table set some_col = ?">
<sql:param value= "someValue"/>
</sql:update>
<sql:update
sql="update table2 set some_col = ?">
<sql:param value= "someValue"/>
</sql:update>
</sql:transaction>
|
<sql:update>
|
Executes an SQL INSERT, UPDATE, or DELETE statement.
|
<sql:update sql="update table set some_col = ?">
<sql:param value= "someValue"/>
</sql:update> |