连接数据库
所有与数据库有关的对象和方法都在 java.sql 包中,因此在使用 JDBC 的程序中必须加入 "import java.sql.* "。 JDBC 要连接 ODBC 数据库,您必须首先加载 JDBC-ODBC 桥驱动程序
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
该语句加载驱动程序,并创建该类的一个实例。然后,要连接一个特定的数据库,您必须创建 Connect 类的一个实例,并使用 URL 语法连接数据库。
String url = "jdbc:odbc:Grocery prices";
Connection con = DriverManager.getConnection(url);
请注意,您使用的数据库名是您在 ODBC 设置面板中输入的“数据源”名称。
URL 语法可能因数据库类型的不同而变化极大。
jdbc:subprotocol:subname
第一组字符代表连接协议,并且始终是 jdbc。还可能有一个子协议,在此处,子协议被指定为 odbc。它规定了一类数据库的连通性机制。如果您要连接其它机器上的数据库服务器,可能也要指定该机器和一个子目录:
jdbc:bark//doggie/elliott
最后,您可能要指定用户名和口令,作为连接字符串的一部分:
jdbc:bark//doggie/elliot;UID=GoodDog;PWD=woof
*******************************************************************************************
*******************************************************************************************
上面给出了连接数据库的一种方法,其实还有另外一种方法,如下:
System.setProperty("jdbc.drivers","sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:Grocery prices";
Connection con=DriverManager.getConnection(url);
说明:
我们可以用System.getProperty("jdbc.drivers")对设定的System属性值进行查询。其实,对于System属性,系统认可的属性如下:
java.version Java Runtime Environment version
java.vendor Java Runtime Environment vendor
java.vendor.url Java vendor URL
java.home Java installation directory
java.vm.specification.version Java Virtual Machine specification version
java.vm.specification.vendor Java Virtual Machine specification vendor
java.vm.specification.name Java Virtual Machine specification name
java.vm.version Java Virtual Machine implementation version
java.vm.vendor Java Virtual Machine implementation vendor
java.vm.name Java Virtual Machine implementation name
java.specification.version Java Runtime Environment specification version
java.specification.vendor Java Runtime Environment specification vendor
java.specification.name Java Runtime Environment specification name
java.class.version Java class format version number
java.class.path Java class path
java.library.path List of paths to search when loading libraries
java.io.tmpdir Default temp file path
java.compiler Name of JIT compiler to use
java.ext.dirs Path of extension directory or directories
os.name Operating system name
os.arch Operating system architecture
os.version Operating system version
file.separator File separator ("/" on UNIX)
path.separator Path separator (":" on UNIX)
line.separator Line separator ("\n" on UNIX)
user.name User's account name
user.home User's home directory
user.dir User's current working directory
大家可以看到其中并没有jdbc.drivers这一个属性,但是System的属性可以随意的由我们来添加,比如我们用setProperty设定了一个名为“bacoo”的属性,并指定该属性值为“test”的话,那么当我们用getProperty时就可以检索到属性bacoo的值为test。这里之所以要加入“jdbc.drivers”这个属性值,是因为DriverManager这个类默认的会在初始化时去System中搜索这一属性的值,在这个属性值中我们可以将多个需要加载的驱动用冒号“:”隔开,又由于DriverManager是一个静态类(其实在定义一个类时,不允许用static修饰,只允许public、final、abstract三个修饰符,这里说其是静态类指的是该类的所有方法和属性<其实该类也没有属性,连构造函数都没有>均是静态的),因此在调用DriverManager.getConnection(url)时,DriverManager需要先初始化,就会加载驱动了。
访问数据库
一旦连接到数据库,就可以请求表名以及表列的名称和内容等信息,而且您可以运行 SQL 语句来查询数据库或者添加或修改其内容。可用来从数据库中获取信息的对象有:
DatabaseMetaData
有关整个数据库的信息:表名、表的索引、数据库产品的名称和版本、数据库支持的操作。
DatabaseMetaData dbmd;
dbmd=con.getMetaData();
下面重点介绍一下DatabaseMetaDat中的两个重要函数getTables和getColumns:
ResultSet
getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types)
仅返回与目录、模式、表名称和(表)类型标准匹配的表描述。
catalog:要在其中查找表名的目录名。对于 JDBC-ODBC 数据库以及许多其他数据库而言,可将其设置为 null。这些数据库的目录项实际上是它在文件系统中的绝对路径名称。
schemaPattern:要包括的数据库“方案”。许多数据库不支持方案,而对另一些数据库而言,它代表数据库所有者的用户名。一般将它设置为 null。
tableNamePattern:一个掩码,用来描述您要检索的表的名称。如果您希望检索所有表名,则将其设为通配符 %。请注意,SQL 中的通配符是 % 符号,而不是一般 PC 用户的 * 符号。
types[]:这是描述您要检索的表的类型的 String 数组。数据库中通常包括许多用于内部处理的表,而对作为用户的您没什么价值。如果它是空值,则您会得到所有这些表。如果您将其设为包含字符串“TABLES”的单元素数组,您将仅获得对用户有用的表格。
例子:
String [] types=new String[1];
types[0]="TABLE";
rs=dbmd.getTables(null, null, "%", types);
Java Doc中说该函数返回的表描述信息都包括以下10种信息,TABLE_CAT、TABLE_SCHEM、TABLE_NAME、TABLE_TYPE、REMARKS、TYPE_CAT、TYPE_SCHEM、TYPE_NAME、SELF_REFERENCING_COL_NAME、REF_GENERATION,但是在实际测试时,返回的结果中只有TABLE_CAT、TABLE_SCHEM、TABLE_NAME、TABLE_TYPE、REMARKS这5项。顺便要说一声的是,变量types可以取的值有:"TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS" 和 "SYNONYM",通常只取TABLE。
*************************************************************************************************************************************************************************************************
ResultSet
getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
仅返回与目录、模式、表和列名称标准匹配的列描述。
通常在得到有关指定表(比如我们这里指定了表名为FoodPrice)的列的描述信息的结果集(rs)之后,我们重点关心的是COLUMN_NAME、DATA_TYPE(数据类型占用的字节数,比如整型就是4)、TYPE_NAME(INTEGER、CURRENCY之类的类型名称),当然最关心的肯定是COLUMN_NAME了。下面把结果集中所有可以得到的信息列给出如下:
TABLE_CAT、TABLE_SCHEM、TABLE_NAME、COLUMN_NAME、DATA_TYPE、TYPE_NAME、COLUMN_SIZE、BUFFER_LENGTH、DECIMAL_DIGITS、NUM_PREC_RADIX、NULLABLE、REMARKS、COLUMN_DEF、SQL_DATA_TYPE、SQL_DATETIME_SUB、CHAR_OCTET_LENGTH、ORDINAL_POSITION、IS_NULLABLE、ORDINAL。
例子:
rs=dbmd.getColumns(null, null, "FoodPrice", null);
因此我们通常用
while(rs.next()){
System.out.print(rs.getString("COLUMN_NAME")+"\t");
}来得到该表中所有的列名称。其实这就是一个从结果集中检索的结果。
ResultSet
关于某个表的信息或一个查询的结果。您必须逐行访问数据行,但是您可以任何顺序访问列。
对于数据库中表的描述信息的结果集可以这样得到:rs=dbmd.getTables(null, null, "%", null);
对于某张表中的列的描述信息的结果集可以这样得到:rs=dbmd.getColumns(null, null, "FoodPrice", null);
对于要从表中检索具体的符合要求的结果集(而不仅仅是一些描述信息了)就必须使用如下的方法:
Statement st=con.createStatement();
String query="SELECT FoodName FROM FOOD;";//注意字符串中要包含“;”!
rs=st.executeQuery(query);
ResultSetMetaData
有关 ResultSet 中列的名称和类型的信息。
ResultSetMetaData rsmd;
rsmd = rs.getMetaData();
numCols = rsmd.getColumnCount();
// 打印列名
for (i = 1; i <= numCols; i++)
System.out.print(rsmd.getColumnName(i) + " ");
System.out.println();
最后,给出一些零散的知识:
(1)对于数据库的连接、访问等等操作都需要放在try和catch块中进行,都有可能抛出SQLException异常,使用该异常类需要import java.sql.*;
(2)前面提到的DatabaseMetaDat、ResultSet、ResultSetMetaData均是接口,而不是类,在下面的例子中,通过跟踪调试,可以发现在程序运行过程中产生的都是基于JdbcOdbc驱动的类,即JdbcOdbcResultSet等类,把这些类(它们都实现了相应的接口)实例化后赋值给ResultSet接口,如ResultSet rs=dbmd.getColumns(null, null, "FoodPrice", null);因此,我们们不难推断出对于其他类型的数据库驱动,均是这样一个原理,同时也理解了为什么Java中有许多接口,而并没有与这些接口对应的实现了它们的类,再一次验证了接口就是一种标准,一种规范。
给出一个完整的例子:
package com.bacoo.www;
import java.sql.*;
public class JdbcOdbcTest {
ResultSet rs;
ResultSetMetaData rsmd;
DatabaseMetaData dbmd;
Connection con;
int numCols,i;
public JdbcOdbcTest(){
System.setProperty("jdbc.drivers","sun.jdbc.odbc.JdbcOdbcDriver");
String url="jdbc:odbc:Groceries";
String query="SELECT DISTINCTROW FoodName FROM Food " +
"WHERE (FoodName like 'C%');";
try{
//Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con=DriverManager.getConnection(url);
dbmd=con.getMetaData();
System.out.println("Connected to:"+dbmd.getURL());
System.out.println("Driver "+ dbmd.getDriverName());
String [] types=new String[1];
types[0]="TABLE";
rs=dbmd.getTables(null, null, "%", null);
dumpResults("--Tables--");
rs.close();
}catch(Exception e){
System.out.println(e);
}
System.out.println("--Column Names--");
try{
rs=dbmd.getColumns(null, null, "FoodPrice", null);
while(rs.next()){
System.out.print(rs.getString("COLUMN_NAME")+" ");
}
System.out.println();
rs.close();
}catch(Exception e){
System.out.println(e);
}
try{
Statement st=con.createStatement();
rs=st.executeQuery("SELECT FoodName FROM FOOD;");
}catch(Exception e){
System.out.println("query exception");
}
dumpResults("--contents of FoodName column--");
try{
Statement st=con.createStatement();
rs=st.executeQuery(query);
}catch(Exception e){
System.out.println("query exception");
}
dumpResults("--Results of Query--");
}
private void dumpResults(String head) {
// 这是打印列标头和每列的内容的
// 通用方法
System.out.println(head);
try {
// 从元数据中获取列数
rsmd = rs.getMetaData();
numCols = rsmd.getColumnCount();
// 打印列名
for (i = 1; i <= numCols; i++)
System.out.print(rsmd.getColumnName(i) + "、");
System.out.println();
// 打印列内容
while (rs.next()) {
for (i = 1; i <= numCols; i++)
System.out.print(rs.getString(i) + "\t");
System.out.println();
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new JdbcOdbcTest();
System.out.println(System.getProperty("jdbc.drivers"));
}
}
运行的结果是:
Connected to:jdbc:odbc:Groceries
Driver JDBC-ODBC Bridge (odbcjt32.dll)
--Tables--
TABLE_CAT、TABLE_SCHEM、TABLE_NAME、TABLE_TYPE、REMARKS、
C:\Documents and Settings\Administrator\桌面\db1 null MSysAccessObjects SYSTEM TABLE null
C:\Documents and Settings\Administrator\桌面\db1 null MSysAccessXML SYSTEM TABLE null
C:\Documents and Settings\Administrator\桌面\db1 null MSysACEs SYSTEM TABLE null
C:\Documents and Settings\Administrator\桌面\db1 null MSysObjects SYSTEM TABLE null
C:\Documents and Settings\Administrator\桌面\db1 null MSysQueries SYSTEM TABLE null
C:\Documents and Settings\Administrator\桌面\db1 null MSysRelationships SYSTEM TABLE null
C:\Documents and Settings\Administrator\桌面\db1 null Food TABLE null
C:\Documents and Settings\Administrator\桌面\db1 null FoodPrice TABLE null
C:\Documents and Settings\Administrator\桌面\db1 null Stores TABLE null
--Column Names--
FSKey StoreKey FoodKey Price
--contents of FoodName column--
FoodName、
Apples
Oranges
Hamburger
Butter
Milk
Coca Cola
Green beans
--Results of Query--
FoodName、
Coca Cola
sun.jdbc.odbc.JdbcOdbcDriver
当然使用该例子,必须要先建立一个数据源。