📄 tij0169.html
字号:
<html><body>
<table width="100%"><tr>
<td>
<a href="http://www.bruceeckel.com/javabook.html">Bruce Eckel's Thinking in Java</a>
</td>
<td align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0168.html">Prev</a> | <a href="tij0170.html">Next</a>
</td>
</tr></table>
<hr>
<H2 ALIGN=LEFT>
Connecting
to databases
<P>with
JDBC
</H2>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">It
has been estimated that half of all software development involves client/server
operations. A great promise of Java has been the ability to build
platform-independent client/server database applications. In Java 1.1<A NAME="Index2828"></A>
this has come to fruition with <A NAME="Index2829"></A><A NAME="Index2830"></A><A NAME="Index2831"></A>Java
DataBase Connectivity (JDBC).
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">One
of the major problems with databases has been the feature wars between the
database companies. There is a “standard” database language, <A NAME="Index2832"></A><A NAME="Index2833"></A>Structured
Query Language (SQL-92), but usually you must know which database vendor
you’re working with despite the standard. JDBC is designed to be
platform-independent, so you don’t need to worry about the database
you’re using while you’re programming. However, it’s still
possible to make vendor-specific calls from JDBC so you aren’t restricted
from doing what you must.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">JDBC,
like many of the APIs in Java, is designed for simplicity. The method calls you
make correspond to the logical operations you’d think of doing when
gathering data from a database: connect to the database, create a statement and
execute the query, and look at the result set.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">To
allow this platform independence, JDBC provides a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>driver
manager
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that dynamically maintains all the driver objects that your database queries
will need. So if you have three different kinds of vendor databases to connect
to, you’ll need three different driver objects. The driver objects
register themselves with the driver manager at the time of loading, and you can
force the loading using
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Class.forName( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">To
open a database, you must create a “<A NAME="Index2834"></A><A NAME="Index2835"></A>database
URL” that specifies:
</FONT><P></DIV>
<OL>
<LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> That
you’re using JDBC with “jdbc”
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> The
“subprotocol”: the name of the driver or the name of a database
connectivity mechanism. Since the design of JDBC was inspired by <A NAME="Index2836"></A>ODBC,
the first subprotocol available is the “jdbc-odbc bridge,”
specified by “odbc”
</FONT><LI><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"> The
database identifier. This varies with the database driver used, but it
generally provides a logical name that is mapped by the database administration
software to a physical directory where the database tables are located. For
your database identifier to have any meaning, you must register the name using
your database administration software. (The process of registration varies from
platform to platform.)
</FONT></OL><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">All
this information is combined into one string, the “database URL.”
For example, to connect through the ODBC subprotocol to a database identified
as “people,” the database URL could be:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">String
dbUrl = "jdbc:odbc:people";
</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you’re connecting across a network, the database URL will also contain
the information identifying the remote machine.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">When
you’re ready to connect to the database, you call the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>DriverManager.getConnection( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
passing it the database URL, the user name, and a password to get into the
database. You get back a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Connection</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object that you can then use to query and manipulate the database.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
following example opens a database of contact information and looks for a
person’s last name as given on the command line. It selects only the
names of people that have email addresses, then prints out all the ones that
match the given last name:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Lookup.java</font>
<font color="#009900">// Looks up email addresses in a </font>
<font color="#009900">// local database using JDBC</font>
<font color="#0000ff">import</font> java.sql.*;
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Lookup {
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
String dbUrl = "jdbc:odbc:people";
String user = "";
String password = "";
<font color="#0000ff">try</font> {
<font color="#009900">// Load the driver (registers itself)</font>
Class.forName(
"sun.jdbc.odbc.JdbcOdbcDriver");
Connection c = DriverManager.getConnection(
dbUrl, user, password);
Statement s = c.createStatement();
<font color="#009900">// SQL code:</font>
ResultSet r =
s.executeQuery(
"SELECT FIRST, LAST, EMAIL " +
"FROM people.csv people " +
"WHERE " +
"(LAST='" + args[0] + "') " +
" AND (EMAIL Is Not Null) " +
"ORDER BY FIRST");
<font color="#0000ff">while</font>(r.next()) {
<font color="#009900">// Capitalization doesn't matter:</font>
System.out.println(
r.getString("Last") + ", "
+ r.getString("fIRST")
+ ": " + r.getString("EMAIL") );
}
s.close(); <font color="#009900">// Also closes ResultSet</font>
} <font color="#0000ff">catch</font>(Exception e) {
e.printStackTrace();
}
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can see the creation of the database URL as previously described. In this
example, there is no password protection on the database so the user name and
password are empty strings.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Once
the connection is made with
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>DriverManager.getConnection( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you can use the resulting
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Connection</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">create
a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Statement</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object using the <A NAME="Index2837"></A><A NAME="Index2838"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>createStatement( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method. With the resulting <A NAME="Index2839"></A><A NAME="Index2840"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Statement</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you can call <A NAME="Index2841"></A><A NAME="Index2842"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>executeQuery( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
passing in a string containing an SQL-92 standard SQL statement. (You’ll
see shortly how you can generate this statement automatically, so you
don’t have to know much about SQL.)
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>executeQuery( )
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">method
returns a <A NAME="Index2843"></A><A NAME="Index2844"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ResultSet</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object, which is quite a bit like an iterator: the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>next( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method moves the iterator to the next record in the statement, or returns
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>null</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
if the end of the result set has been reached. You’ll always get a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>ResultSet</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object back from
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>executeQuery( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
even if a query results in an empty set (that is, an exception is not thrown).
Note that you must call
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>next( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
once before trying to read any record data. If the result set is empty, this
first call to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>next( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
will return
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>false</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
For each record in the result set, you can select the fields using (among other
approaches) the field name as a string. Also note that the capitalization of
the field name is ignored – it doesn’t matter with an SQL database.
You determine the type you’ll get back by calling <A NAME="Index2845"></A><A NAME="Index2846"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>getInt( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
<A NAME="Index2847"></A><A NAME="Index2848"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>getString( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
<A NAME="Index2849"></A><A NAME="Index2850"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>getFloat( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
etc. At this point, you’ve got your database data in Java native format
and can do whatever you want with it using ordinary Java code.
</FONT><a name="_Toc408018782"></a><P></DIV>
<A NAME="Heading534"></A><H3 ALIGN=LEFT>
Getting
the example to work
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">With
JDBC, understanding the code is relatively simple. The confusing part is making
it work on your particular system. The reason this is confusing is that it
requires you to figure out how to get your JDBC driver to load properly, and
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -