Cover | Table of Contents | Colophon
DELETE,
INSERT, SELECT, and
UPDATE statements. For a short overview of SQL,
check out Chapter 2.|
Artist
|
Title
|
Category
|
Year
|
|---|---|---|---|
|
The Cure
|
Pornography
|
Alternative
|
SELECT and select are treated
exactly the same. Depending on your database, however, table and
column names may or may not be case-insensitive. In addition, the
space between words in a SQL statement is unimportant. You can have a
newline after each word, several spaces, or just a single space.
Throughout this book I use the convention of placing SQL keywords in
all capitals and separating single SQL statements across multiple
lines for readability.SELECT title FROM albums
SELECT,
INSERT, UPDATE, and
DELETE. You can issue SQL statements in several
ways. The simplest, quickest way is through a SQL command-line tool.
Each database engine comes with its own. Throughout most of this
book, however, you will send your SQL as Java strings to JDBC
methods.
INSERT, UPDATE, or
DELETE) or queries (SELECT). In
the next chapter, you will discuss more complex database access that
allows you to execute statements of unknown types.Connection
object you created in the previous section. When this object first
gets created, it is simply a direct link to the database. You use a
Connection object to generate implementations of
java.sql.Statement tied to the same database
transaction. After you have used one or more
Statement objects generated by your
Connection, you can use it to commit or rollback
the Statement objects associated with that
Connection.
Statement is very
much what its name implies—a SQL statement. Once you get a
Statement object from a
Connection, you have what amounts to a blank check
that you can write against the transaction represented by that
Connection. You do not actually assign SQL to the
Statement until you are ready to send the SQL to
the database.java.sql.ResultSet, while the method for
nonqueries returns an integer. A ResultSet
provides you with access to the data retrieved by a query.Connection, the Statement, and
the ResultSet. You will use them everytime you
write JDBC code. This book has already discussed the details of the
Connection class.VARCHAR datatype.
Java actually has no concept of a variable width, single-byte
character array; Java doesn't even have a single-byte character
type. The closest thing is the
String class.NUMERIC
type. JDBC, fortunately, lets you retrieve data in their Java forms
defined by a JDBC-specified datatype mapping. You do not need to
worry that a SQL LONG has a different
representation in Sybase than it does in Oracle. You just call the
ResultSet
getLong() method to
retrieve numbers you wish to treat as Java longs.getInt(), you risk getting bad data. Similarly,
if you save a Java float into a numeric field with a scale of 0, you
will lose data. The important rule of thumb for Java programming,
however, is think and work in Java and use the database to support
the Java application. Do not let the database drive Java. Table 3.2 shows the JDBC prescribed SQL to Java datatype
mappings. Table 3.3 shows the reverse mappings. A
full discussion of the SQL3 mappings will occur in Chapter 4.
|
SQL Type (from java.sql.Types) |
|---|
createStatement(
) method. The Connection class actually
has two versions of createStatement()—the
zero parameter version you have used so far and a two parameter
version that supports the creation of Statement
instances that generate scrollable ResultSet
objects. The default call translates to the following call:conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);
ResultSet.TYPE_FORWARD_ONLY indicates that any
ResultSet generated by the
Statement returned from
createStatement() only moves forward (the JDBC
1.x behavior). The second argument is the result set concurrency. The
value ResultSet.CONCUR_READ_ONLY specifies that
each row from a ResultSet is read-only. As you
will see in the next chapter, rows from a
ResultSet can be modified in place if the
concurrency specified in the createStatement()
call allows it.java.util classes like
java.sql.Date and
java.sql.Numeric. Others are exception classes
that get thrown by JDBC calls.Types class provides
constants that identify SQL datatypes. Each constant representing a
SQL datatype that is mapped to an integer is defined by the XOPEN SQL
specification. You will see this class used extensively in the next
chapter.SQLException
class
extends the general java.lang.Exception class that
provides extra information about a database error. The information
provided by SQLException includes:Exception
class's getMessage() method.try {
Connection connection = DriverManager.getConnection(url, uid,
pass);
}
catch( SQLException e ) {
while( e != null ) {
System.err.println("SQLState: " + e.getSQLState( ));
System.err.println(" Code: " + e.getErrorCode( ));
System.err.println(" Message:");
System.err.println(e.getMessage( ));
e = e.getNextException( );
}
}init(
)
method.
Like init() in applets, it is where a servlet
does its initialization. It accepts the
ServletConfig instance for this servlet from which
you can grab initialization parameters. For this example, I have
prefixed all initialization parameters with "gb.":public void init(ServletConfig cfg) throws ServletException {
super.init(cfg);
driverName = cfg.getInitParameter("gb.driver");
jdbcURL = cfg.getInitParameter("gb.jdbcURL");
connectionProperties.put("user", cfg.getInitParameter("gb.user"));
connectionProperties.put("password", cfg.getInitParameter("gb.pw"));
try {
driver = (Driver)Class.forName(driverName).newInstance( );
}
catch( Exception e ) {
throw new ServletException("Unable to load driver: " +
e.getMessage( ));
}
}
ServletConfig object
holds runtime configuration information. Use this information to
capture all JDBC runtime configuration and save it in the
UPDATE ACCOUNT SET BALANCE
=
XXX
WHERE ACCOUNT_ID
=
YYY, you would force the
database to rebuild the same query plan each time you changed the
balance for the account. Databases enable you to optimize repeated
calls through prepared SQL.Statement (or one of its subclasses) to be
submitted together for execution by the database. Using the
techniques you have learned so far in this book, account
interest-calculation processing occurs roughly in the following
fashion:ResultSet.CONCUR_READ_ONLY. In other words, you
cannot make changes to data in the result sets you have seen without
creating a new update statement based on the data from your result
set. Along with scrollable result sets, JDBC 2.0 also introduces the
concept of updatable result sets—result
sets you can change.ResultSet.CONCUR_READ_ONLY
and
ResultSet.CONCUR_UPDATABLE
. You already know how to
create an updatable result set from the discussion of scrollable
result sets in Chapter 3. You pass the concurrency
type ResultSet.CONCUR_UPDATABLE as the second
argument to createStatement(), or the third
argument to prepareStatement() or
prepareCall():PreparedStatement stmt = conn.prepareStatement(
"SELECT acct_id, balance FROM account",
ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
BLOB and CLOB
datatypes, few of these advanced datatype features are likely to be
relevant to most programmers for a few years. While they are
important features for bridging the gap between the object and
relational paradigms, they are light years ahead of where database
vendors are with relational technology and how people use relational
technology today.BLOB datatype, hold large amounts of binary
data. Similarly, clobs, represented by the CLOB
datatype, hold large amounts of text data.VARCHAR
and
VARBINARY
datatypes. These two old datatypes
have two important implementation problems that make them impractical
for large amounts of data. First, they tend to have rather small
maximum data sizes. Second, you retrieve them from the database all
at once. While the first problem is more of a tactical issue (those
maximum sizes are arbitrary), the second problem is more serious.
Fields with sizes of 100 KB or more are better served through
streaming than an all-at-once approach. In other words, instead of
having your query wait to fetch the full data for each row in a
result set containing a column of 1-MB data, it makes more sense to
not send that data across the network until the instant you ask for
it. The query runs faster using streaming, and your network will not
be overburdened trying to shove 10 rows of 1 MB each at a client
machine all at once. The java.sql.ResultSetMetaData and
java.sql.DatabaseMetaData. The meta-data described
by these classes was included in the original JDBC
ResultSet and Connection
classes. The team that developed the JDBC specification decided
instead that it was better to keep the ResultSet
and Connection classes small and simple to serve
the most common database requirements. The extra functionality could
be served by creating meta-data classes to provide the often esoteric
information required by a minority of developers.ResultSetMetaData
class provides extra information about
ResultSet objects returned from a database query.
In the embedded queries you made earlier in the book, you hardcoded
into your queries much of the information a
ResultSetMetaData object gives you. This class
provides you with answers to the following questions:NULL a valid value for a given column?