Main entry point
for the application */ public static void main(String
args[]) { try {
// Perform the simple query and display the
results performQuery(); } catch (Exception ex)
{ ex.printStackTrace(); } }
public static void performQuery() throws Exception { // The
name of the JDBC driver to use String driverName =
"sun.jdbc.odbc.JdbcOdbcDriver";
// The JDBC connection URL String connectionURL =
"jdbc:odbc:MyAccessDataSource";
// The JDBC Connection object Connection con = null;
// The JDBC Statement object Statement stmt = null;
// The SQL statement to execute String sqlStatement
= "SELECT Empno, Name, Position FROM Employee";
// The JDBC
ResultSet object ResultSet rs = null;
try {
System.out.println("Registering " + driverName);
// Create
an instance of the JDBC driver so that it has // a chance to register
itself Class.forName(driverName).newInstance();
System.out.println("Connecting to " + connectionURL);
//
Create a new database connection. We're assuming that // additional
properties (such as username and password) // are not
necessary con = DriverManager.getConnection(connectionURL);
// Create a statement object that we can execute queries //
with stmt = con.createStatement();
// Execute the query rs = stmt.executeQuery(sqlStatement);
// Process the results. First dump out the column // headers as
found in the ResultSetMetaData ResultSetMetaData rsmd =
rs.getMetaData();
int columnCount = rsmd.getColumnCount();
System.out.println(""); String line = ""; for (int i =
0; i < columnCount; i++) { if (i > 0) { line += ",
"; }
// Note that the column index is 1-based line +=
rsmd.getColumnLabel(i + 1); } System.out.println(line);
// Count the number of rows int rowCount = 0;
// Now
walk through the entire ResultSet and get each // row while
(rs.next()) { rowCount++;
// Dump out the values of each
row line = ""; for (int i = 0; i < columnCount; i++)
{ if (i > 0) { line += ", "; }
// Note that the column index is 1-based line +=
rs.getString(i + 1); } System.out.println(line); }
This is a simple servlet that will use JDBC to gather
all * of the employee information from a database and format it * into
an HTML table. */
public class EmployeeList extends HttpServlet { /** *
Performs the HTTP GET operation * * @param req The request
from the client * @param resp The response from the servlet */
public void doGet(HttpServletRequest req, HttpServletResponse
resp) throws ServletException, java.io.IOException { // Set
the content type of the response resp.setContentType("text/html");
// Create a PrintWriter to write the response java.io.PrintWriter
out = new java.io.PrintWriter(resp.getOutputStream());
// Print the HTML
header out.println(""); out.println("
"); out.println("Employees
for Nezzer's Chocolate
Factory"); out.println("
"); out.println(" ");
// Create any addition properties necessary for connecting // to
the database, such as user and password java.util.Properties props = new
java.util.Properties(); props.put("user",
"karlmoss"); props.put("password",
"larryboy");
query("sun.jdbc.odbc.JdbcOdbcDriver", "jdbc:odbc:MyAccessDataSource", props, "SELECT
Empno, Name, Position FROM Employee", out);
// Wrap
up out.println(""); out.flush(); out.close(); }
/** *
Initialize the servlet. This is called once when
the * servlet is loaded. It is guaranteed to complete before any *
requests are made to the servlet * * @param cfg Servlet
configuration information */
public void init(ServletConfig cfg) throws
ServletException { super.init(cfg); }
/** *
Destroy the servlet. This is called once when the
servlet * is unloaded. */
public void destroy() { super.destroy(); }
/** *
Given the JDBC driver name, URL, and query
string, * execute the query and format the results into an * HTML
table * * @param driverName JDBC driver name * @param
connectionURL JDBC connection URL * @param props Addition connection
properties, such as user * and password * @param query SQL query to
execute * @param out PrintWriter to use to output the query
results * @return true if the query was successful */
// The JDBC Connection object Connection con =
null;
// The JDBC Statement object Statement stmt = null;
// The JDBC ResultSet object ResultSet rs = null;
// Keep stats for how long it takes to execute // the
query long startMS = System.currentTimeMillis();
// Keep the number of rows in the ResultSet int rowCount =
0;
try {
// Create an instance of the JDBC driver so that it has // a
chance to register itself Class.forName(driverName).newInstance();
// Create a new database connection. con =
DriverManager.getConnection(connectionURL, props);
// Create a statement object that we can execute queries //
with stmt = con.createStatement();
// Execute the query rs = stmt.executeQuery(query);
// Format the results into an HTML table rowCount =
formatTable(rs, out);
} catch (Exception ex) { // Send the error back to the
client out.println("Exception!"); ex.printStackTrace(out); rc
= false; } finally { try { // Always close
properly if (rs != null) { rs.close(); } if
(stmt != null) { stmt.close(); } if (con != null)
{ con.close(); } } catch (Exception ex)
{ // Ignore any errors here } }
// If we queried the table successfully, output some //
statistics if (rc) { long elapsed = System.currentTimeMillis() -
startMS; out.println(" " + rowCount + " rows in "
+ elapsed + "ms"); }
return rc; }
/** *
Given a JDBC ResultSet, format the results
into * an HTML table * * @param rs JDBC ResultSet *
@param out PrintWriter to use to output the table * @return The number of
rows in the ResultSet */
private int formatTable(java.sql.ResultSet rs, java.io.PrintWriter
out) throws Exception { int rowCount = 0;
//
Create the table out.println("
");
// Process the results. First dump out the
column // headers as found in the
ResultSetMetaData ResultSetMetaData rsmd =
rs.getMetaData();
int columnCount = rsmd.getColumnCount();
// Start the table row out.println("
");
for
(int i = 0; i < columnCount; i++) {
// Create each table header. Note that the column index // is
1-based out.println("
" + rsmd.getColumnLabel(i + 1)
+ "
"); }
// End the table row out.println("
");
//
Now walk through the entire ResultSet and get each // row while
(rs.next()) { rowCount++;
// Start a table row out.println("
");
//
Dump out the values of each row for (int i = 0; i < columnCount; i++)
{
// Create the table data. Note that the column index //
is 1-based out.println("
Given a JDBC ResultSet, format the results into *
an HTML table * * @param rs JDBC ResultSet * @param out
PrintWriter to use to output the table * @param uri Requesting URI *
@return The number of rows in the ResultSet */
private int formatTable(java.sql.ResultSet rs, java.io.PrintWriter
out, String uri) throws Exception { int rowsPerPage =
10; int rowCount = 0;
// Keep track of the last year found String lastYear = "";
// This will be true if there is still more data in the //
table boolean more = false;
// Create the
table out.println("
");
//
Process the results. First dump out the column // headers as found in the
ResultSetMetaData ResultSetMetaData rsmd = rs.getMetaData();
int
columnCount = rsmd.getColumnCount();
// Start the table row out.println("
");
for
(int i = 0; i < columnCount; i++) {
// Create each table header. Note that the column index // is
1-based out.println("
" + rsmd.getColumnLabel(i + 1)
+ "
"); }
// End the table row out.println("
");
// Now
walk through the entire ResultSet and get each // row while
(rs.next()) { rowCount++;
// Start a table row out.println("
");
//
Dump out the values of each row for (int i = 0; i < columnCount; i++)
{
// Create the table data. Note that the column
index // is 1-based String data = rs.getString(i +
1); out.println("
" + data + "
");
// If this is the year column, cache it if (i == 0)
{ lastYear = data; } }
// End the table row out.println("
");
// If we are keeping track of the maximum number of // rows per
page and we have exceeded that count // break out of the loop if
((rowsPerPage > 0) && (rowCount >= rowsPerPage))
{ // Find out if there are any more rows after this one more
= rs.next(); break; } }
//Get the last year shown on the page that //called us. Remember that
we are sorting //the years in descending order. String
lastYear="9999"; String
lastYear=req.getParameter("lastYear"); if(lastYear==null){ //No year
was found;must be the first page. lastYear="9999"; }
图9.14 获取一个参数值的Java代码
我使用hidden域的值来生成SQL语句: SELECT * from IndyWinners where year lastYear的缺省值是9999,所以如果没有设置这个参数(当servlet第一次被调用时),所有年份的数据都被选出。否则,只查找那些lastYear以前的年份的情况。请注意我将数据按年降序排列,所以选显示新近的优胜者。这样的查询实际上效率不高而且可能是不准确的。每一次按下Next按钮,就会执行一个新的查询,如果数据库引擎不缓存上一次查询结果的话,这实在是太费时了。另外,如果碰巧其他用户悠了这个表——添加、删除或是修改了某一行,那么新的查询将会显示出这些变化。理想情况下,我们只有一个结果集,我们可以用它来前后移动以适应用户请求。不幸的是,JDBC1.x只允许向前移动。不过JDBC2.0将允许驱动程序利用扩展的游标支持,这样这个任务就可以实现了。 还要注意到这种办法只在表有惟一键的时候才起作用(我们的例子中是年份)。我们必须能够惟一标识我们显示的上一行,这样我们才能取得上一次结束的地方。实现这一点,最简单的办法是用惟一的行标识符,例如ORACLE的ROWID。这个ROWID在所有表中都有,而且你可将它惟一地用于引用行。你可以用DatabaseMetaData.getBestRowIdentifier()来查询当前数据库中是否存在某种惟一标识符。如果不存在记录的惟一标识符,那么你就得设计你的表使之具有一个惟一键。由于我使用的Microsoft
Access不支持惟一的行标识符,所以我使用了你惟一的年份这一列。
图9.15显示了这个查询的第一页,图9.16显示了Next按钮按下之后显示的结果。