JDBC 驱动程序的类型
Java 程序连接数据库的方法实际上有四种:
1. JDBC-ODBC 桥和 ODBC 驱动程序 -- 在这种方式下,这是一个本地解决方案,因为 ODBC 驱动程序和桥代码必须出现在用户的每台机器中。从根本上说这是一个临时解决方案。
2. 本机代码和 Java 驱动程序 -- 它用另一个本地解决方案(该平台上的 Java 可调用的本机代码)取代 ODBC 和 JDBC-ODBC 桥。
3. JDBC 网络的纯 Java 驱动程序 -- 由 Java 驱动程序翻译的 JDBC 形成传送给服务器的独立协议。然后,服务器可连接任何数量的数据库。这种方法使您可能从客户机 Applet 中调用服务器,并将结果返回到您的 Applet。在这种情况下,中间件软件提供商可提供服务器。
4. 本机协议 Java 驱动程序 -- Java 驱动程序直接转换为该数据库的协议并进行调用。这种方法也可以通过网络使用,而且可以在 Web 浏览器的 Applet 中显示结果。在这种情况下,每个数据库厂商将提供驱动程序。
如果您希望编写代码来处理 PC 客户机数据库,如 dBase、Foxbase 或 Access,则您可能会使用第一种方法,并且拥有用户机器上的所有代码。更大的客户机-服务器数据库产品(如 IBM 的 DB2)已提供了第 3 级别的驱动程序。
两层模型和三层模型
当数据库和查询它的应用程序在同一台机器上,而且没有服务器代码的干预时,我们将生成的程序称为两层模型。一层是应用程序,而另一层是数据库。在 JDBC-ODBC 桥系统中通常是这种情况。
当一个应用程序或 applet 调用服务器,服务器再去调用数据库时,我们称其为三层模型。当您调用称为“服务器”的程序时通常是这种情况。
编写 JDBC 代码访问数据库
用 ODBC 注册您的数据库
连接数据库
所有与数据库有关的对象和方法都在 java.sql 包中,因此在使用 JDBC 的程序中必须加入 "import java.sql.* "。 JDBC 要连接 ODBC 数据库,您必须首先加载 JDBC-ODBC 桥驱动程序
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
该语句加载驱动程序,并创建该类的一个实例。然后,要连接一个特定的数据库,您必须创建 Connect 类的一个实例,并使用 URL 语法连接数据库。
String url = "jdbc:odbc:Northwind";
Connection con = DriverManager.getConnection(url);
请注意,您使用的数据库名是您在 ODBC 设置面板中输入的“数据源”名称。
URL 语法可能因数据库类型的不同而变化极大。
jdbc:subprotocol:subname
第一组字符代表连接协议,并且始终是 jdbc。还可能有一个子协议,在此处,子协议被指定为 odbc。它规定了一类数据库的连通性机制。如果您要连接其它机器上的数据库服务器,可能也要指定该机器和一个子目录:
jdbc:bark//doggie/elliott
最后,您可能要指定用户名和口令,作为连接字符串的一部分:
jdbc:bark//doggie/elliot;UID=GoodDog;PWD=woof
访问MSSQL Server方法:(驱动程序需要:msutil.jar,msbase.jar,mssqlServer.jar)
DBDriver=com.microsoft.jdbc.sqlserver.SQLServerDriver
URL=jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=demo
username=sa
password=
maxcon=10
mincon=1
poolName=SkyDev
利用我们开发的数据库类,使用方法如下:
访问数据库
一旦连接到数据库,就可以请求表名以及表列的名称和内容等信息,而且您可以运行 SQL 语句来查询数据库或者添加或修改其内容。可用来从数据库中获取信息的对象有:
DatabaseMetaData 有关整个数据库的信息:表名、表的索引、数据库产品的名称和版本、数据库支持的操作。
ResultSet 关于某个表的信息或一个查询的结果。您必须逐行访问数据行,但是您可以任何顺序访问列。
ResultSetMetaData 有关 ResultSet 中列的名称和类型的信息。
尽管每个对象都有大量的方法让您获得数据库元素的极为详细的信息,但在每个对象中都有几种主要的方法使您可获得数据的最重要信息。然而,如果您希望看到比此处更多的信息,建议您学习文档以获得其余方法的说明。
ResultSet
ResultSet 对象是 JDBC 中最重要的单个对象。从本质上讲,它是对一个一般宽度和未知长度的表的一种抽象。几乎所有的方法和查询都将数据作为 ResultSet 返回。ResultSet 包含任意数量的命名列,您可以按名称访问这些列。它还包含一个或多个行,您可以按顺序自上而下逐一访问。在您使用 ResultSet 之前,必须查询它包含多少个列。此信息存储在 ResultSetMetaData 对象中。
当您获得一个 ResultSet 时,它正好指向第一行之前的位置。您可以使用 next() 方法得到其他每一行,当没有更多行时,该方法会返回 false。由于从数据库中获取数据可能会导致错误,您必须始终将结果集处理语句包括在一个 try 块中。
您可以多种形式获取 ResultSet 中的数据,这取决于每个列中存储的数据类型。另外,您可以按列序号或列名获取列的内容。请注意,列序号从 1 开始,而不是从 0 开始。ResultSet 对象的一些最常用方法如下所示。
getInt(int); 将序号为 int 的列的内容作为整数返回。
getInt(String); 将名称为 String 的列的内容作为整数返回。
getFloat(int); 将序号为 int 的列的内容作为一个 float 型数返回。
getFloat(String); 将名称为 String 的列的内容作为 float 型数返回。
getDate(int); 将序号为 int 的列的内容作为日期返回。
getDate(String); 将名称为 String 的列的内容作为日期返回。
next(); 将行指针移到下一行。如果没有剩余行,则返回 false。
Close(); 关闭结果集。
getMetaData(); 返回 ResultSetMetaData 对象。
ResultSetMetaData
您使用 getMetaData() 方法从 ResultSet 中获取 ResultSetMetaData 对象。您可以使用此对象获得列的数目和类型以及每一列的名称。
getColumnCount(); 返回 ResultSet 中的列数。
getColumnName(int); 返回列序号为 int 的列名。
getColumnLabel(int); 返回此列暗含的标签。
isCurrency(int); 如果此列包含带有货币单位的一个数字,则返回 true。
isReadOnly(int); 如果此列为只读,则返回 true。
isAutoIncrement(int); 如果此列自动递增,则返回 true。这类列通常为键,而且始终是只读的。
getColumnType(int); 返回此列的 SQL 数据类型。这些数据类型包括
BIGINT
BINARY
BIT
CHAR
DATE
DECIMAL
DOUBLE
FLOAT
INTEGER
LONGVARBINARY
LONGVARCHAR
NULL
NUMERIC
OTHER
REAL
SMALLINT
TIME
TIMESTAMP
TINYINT
VARBINARY
VARCHAR
DatabaseMetaData
DatabaseMetaData 对象可为您提供整个数据库的信息。您主要用它获取数据库中表的名称,以及表中列的名称。由于不同的数据库支持不同的 SQL 变体,因此,也有多种方法查询数据库支持哪些 SQL 方法。
getCatalogs() 返回该数据库中的信息目录列表。使用 JDBC-ODBC Bridge 驱动程序,您可以获得用 ODBC 注册的数据库列表。这很少用于 JDBC-ODBC 数据库。
getTables(catalog, schema,tableNames, columnNames) 返回表名与 tableNames 相符而且列名与 columnNames 相符的所有表的说明。
getColumns(catalog, schema,tableNames, columnNames) 返回表名与 tableNames 相符而且列名与 columnNames 相符的所有表列说明。
getURL(); 获得您所连接的 URL 名称。
getDriverName(); 获得您所连接的数据库驱动程序的名称。
获取有关表的信息
您可以使用 DataBaseMetaData 的 getTables() 方法来获取数据库中表的信息。这个方法有如下4个 String 参数:
results =dma.getTables(catalog, schema, tablemask, types[]);
其中参数的意义是:
Catalog 要在其中查找表名的目录名。对于 JDBC-ODBC 数据库以及许多其他数据库而言,可将其设置为 null。这些数据库的目录项实际上是它在文件系统中的绝对路径名称。
Schema 要包括的数据库“方案”。许多数据库不支持方案,而对另一些数据库而言,它代表数据库所有者的用户名。一般将它设置为 null。
Tablemask 一个掩码,用来描述您要检索的表的名称。如果您希望检索所有表名,则将其设为通配符 %。请注意,SQL 中的通配符是 % 符号,而不是一般 PC 用户的 * 符号。
types[] 这是描述您要检索的表的类型的 String 数组。数据库中通常包括许多用于内部处理的表,而对作为用户的您没什么价值。如果它是空值,则您会得到所有这些表。如果您将其设为包含字符串“TABLES”的单元素数组,您将仅获得对用户有用的表格。
一个简单的 JDBC 程序
我们已经学习了 JDBC 的所有基本功能,现在我们可以编写一个简单的程序,该程序打开数据库,打印它的表名以及某一表列的内容,然后对该数据库执行查询。此程序如下所示:
补充高级内容
关于调用SQLServer存储过程的例子:(用到了我们开发的数据库连接类)
使用输出参数:
使用返回参数的例子:
Java 程序连接数据库的方法实际上有四种:
1. JDBC-ODBC 桥和 ODBC 驱动程序 -- 在这种方式下,这是一个本地解决方案,因为 ODBC 驱动程序和桥代码必须出现在用户的每台机器中。从根本上说这是一个临时解决方案。
2. 本机代码和 Java 驱动程序 -- 它用另一个本地解决方案(该平台上的 Java 可调用的本机代码)取代 ODBC 和 JDBC-ODBC 桥。
3. JDBC 网络的纯 Java 驱动程序 -- 由 Java 驱动程序翻译的 JDBC 形成传送给服务器的独立协议。然后,服务器可连接任何数量的数据库。这种方法使您可能从客户机 Applet 中调用服务器,并将结果返回到您的 Applet。在这种情况下,中间件软件提供商可提供服务器。
4. 本机协议 Java 驱动程序 -- Java 驱动程序直接转换为该数据库的协议并进行调用。这种方法也可以通过网络使用,而且可以在 Web 浏览器的 Applet 中显示结果。在这种情况下,每个数据库厂商将提供驱动程序。
如果您希望编写代码来处理 PC 客户机数据库,如 dBase、Foxbase 或 Access,则您可能会使用第一种方法,并且拥有用户机器上的所有代码。更大的客户机-服务器数据库产品(如 IBM 的 DB2)已提供了第 3 级别的驱动程序。
两层模型和三层模型
当数据库和查询它的应用程序在同一台机器上,而且没有服务器代码的干预时,我们将生成的程序称为两层模型。一层是应用程序,而另一层是数据库。在 JDBC-ODBC 桥系统中通常是这种情况。
当一个应用程序或 applet 调用服务器,服务器再去调用数据库时,我们称其为三层模型。当您调用称为“服务器”的程序时通常是这种情况。
编写 JDBC 代码访问数据库
用 ODBC 注册您的数据库
作者:qs1976
出处:论坛
责任编辑: 方舟
[ 2004-01-31 13:21 ]
数据库是以某种文件结构存储的一系列信息表,这种文件结构使您能够访问这些表、选择表中的列、对表进行排序以及根据各种标准选择行
所有与数据库有关的对象和方法都在 java.sql 包中,因此在使用 JDBC 的程序中必须加入 "import java.sql.* "。 JDBC 要连接 ODBC 数据库,您必须首先加载 JDBC-ODBC 桥驱动程序
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
该语句加载驱动程序,并创建该类的一个实例。然后,要连接一个特定的数据库,您必须创建 Connect 类的一个实例,并使用 URL 语法连接数据库。
String url = "jdbc:odbc:Northwind";
Connection con = DriverManager.getConnection(url);
请注意,您使用的数据库名是您在 ODBC 设置面板中输入的“数据源”名称。
URL 语法可能因数据库类型的不同而变化极大。
jdbc:subprotocol:subname
第一组字符代表连接协议,并且始终是 jdbc。还可能有一个子协议,在此处,子协议被指定为 odbc。它规定了一类数据库的连通性机制。如果您要连接其它机器上的数据库服务器,可能也要指定该机器和一个子目录:
jdbc:bark//doggie/elliott
最后,您可能要指定用户名和口令,作为连接字符串的一部分:
jdbc:bark//doggie/elliot;UID=GoodDog;PWD=woof
访问MSSQL Server方法:(驱动程序需要:msutil.jar,msbase.jar,mssqlServer.jar)
DBDriver=com.microsoft.jdbc.sqlserver.SQLServerDriver
URL=jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=demo
username=sa
password=
maxcon=10
mincon=1
poolName=SkyDev
利用我们开发的数据库类,使用方法如下:
DbObject DbO = new DbObject(new SqlServerConnectionFactory("localhost", 1433, "demo", "sa", "")); Connection con = DbO.getConnection(); //类代码(不含连接工厂实现) package skydev.modules.data; public final class SqlServerConnectionFactory extends ConnectionFactory { private final String dbDriver = "com.microsoft.jdbc.sqlserver.SQLServerDriver"; private String host; private int port; private String databaseName; public SqlServerConnectionFactory() { super.setDriverName(dbDriver); } /** * * @param host 数据库所在的主机名:如"localhost" * @param port SQL服务器运行的端口号,如果使用缺省值 1433,传入一个负数即可 * @param databaseName 数据库名称 * @param userName 用户名 * @param password 口令 */ public SqlServerConnectionFactory(String host, int port, String databaseName, String userName, String password) { this.setHost(host); this.setPort(port); this.setDatabaseName(databaseName); this.setUserName(userName); this.setPassword(password); init(); } private void init() { super.setDriverName(dbDriver); super.setUrl("jdbc:microsoft:sqlserver://" + host.trim() + ":" + new Integer(port).toString() + ";DatabaseName=" + databaseName.trim()); //super.setUrl("jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=demo"); } …… //------------------------------------------------------------------------------------ 访问MySQL的方法: DBDriver=com.mysql.jdbc.Driver URL=jdbc:mysql://localhost/demo username= password= maxcon=5 mincon=1 poolName=zhengmao |
作者:qs1976
出处:论坛
责任编辑: 方舟
[ 2004-01-31 13:21 ]
数据库是以某种文件结构存储的一系列信息表,这种文件结构使您能够访问这些表、选择表中的列、对表进行排序以及根据各种标准选择行
一旦连接到数据库,就可以请求表名以及表列的名称和内容等信息,而且您可以运行 SQL 语句来查询数据库或者添加或修改其内容。可用来从数据库中获取信息的对象有:
DatabaseMetaData 有关整个数据库的信息:表名、表的索引、数据库产品的名称和版本、数据库支持的操作。
ResultSet 关于某个表的信息或一个查询的结果。您必须逐行访问数据行,但是您可以任何顺序访问列。
ResultSetMetaData 有关 ResultSet 中列的名称和类型的信息。
尽管每个对象都有大量的方法让您获得数据库元素的极为详细的信息,但在每个对象中都有几种主要的方法使您可获得数据的最重要信息。然而,如果您希望看到比此处更多的信息,建议您学习文档以获得其余方法的说明。
ResultSet
ResultSet 对象是 JDBC 中最重要的单个对象。从本质上讲,它是对一个一般宽度和未知长度的表的一种抽象。几乎所有的方法和查询都将数据作为 ResultSet 返回。ResultSet 包含任意数量的命名列,您可以按名称访问这些列。它还包含一个或多个行,您可以按顺序自上而下逐一访问。在您使用 ResultSet 之前,必须查询它包含多少个列。此信息存储在 ResultSetMetaData 对象中。
//从元数据中获得列数 ResultSetMetaData rsmd; rsmd = results.getMetaData(); numCols = rsmd.getColumnCount(); |
当您获得一个 ResultSet 时,它正好指向第一行之前的位置。您可以使用 next() 方法得到其他每一行,当没有更多行时,该方法会返回 false。由于从数据库中获取数据可能会导致错误,您必须始终将结果集处理语句包括在一个 try 块中。
您可以多种形式获取 ResultSet 中的数据,这取决于每个列中存储的数据类型。另外,您可以按列序号或列名获取列的内容。请注意,列序号从 1 开始,而不是从 0 开始。ResultSet 对象的一些最常用方法如下所示。
getInt(int); 将序号为 int 的列的内容作为整数返回。
getInt(String); 将名称为 String 的列的内容作为整数返回。
getFloat(int); 将序号为 int 的列的内容作为一个 float 型数返回。
getFloat(String); 将名称为 String 的列的内容作为 float 型数返回。
getDate(int); 将序号为 int 的列的内容作为日期返回。
getDate(String); 将名称为 String 的列的内容作为日期返回。
next(); 将行指针移到下一行。如果没有剩余行,则返回 false。
Close(); 关闭结果集。
getMetaData(); 返回 ResultSetMetaData 对象。
ResultSetMetaData
您使用 getMetaData() 方法从 ResultSet 中获取 ResultSetMetaData 对象。您可以使用此对象获得列的数目和类型以及每一列的名称。
getColumnCount(); 返回 ResultSet 中的列数。
getColumnName(int); 返回列序号为 int 的列名。
getColumnLabel(int); 返回此列暗含的标签。
isCurrency(int); 如果此列包含带有货币单位的一个数字,则返回 true。
isReadOnly(int); 如果此列为只读,则返回 true。
isAutoIncrement(int); 如果此列自动递增,则返回 true。这类列通常为键,而且始终是只读的。
getColumnType(int); 返回此列的 SQL 数据类型。这些数据类型包括
BIGINT
BINARY
BIT
CHAR
DATE
DECIMAL
DOUBLE
FLOAT
INTEGER
LONGVARBINARY
LONGVARCHAR
NULL
NUMERIC
OTHER
REAL
SMALLINT
TIME
TIMESTAMP
TINYINT
VARBINARY
VARCHAR
DatabaseMetaData
DatabaseMetaData 对象可为您提供整个数据库的信息。您主要用它获取数据库中表的名称,以及表中列的名称。由于不同的数据库支持不同的 SQL 变体,因此,也有多种方法查询数据库支持哪些 SQL 方法。
getCatalogs() 返回该数据库中的信息目录列表。使用 JDBC-ODBC Bridge 驱动程序,您可以获得用 ODBC 注册的数据库列表。这很少用于 JDBC-ODBC 数据库。
getTables(catalog, schema,tableNames, columnNames) 返回表名与 tableNames 相符而且列名与 columnNames 相符的所有表的说明。
getColumns(catalog, schema,tableNames, columnNames) 返回表名与 tableNames 相符而且列名与 columnNames 相符的所有表列说明。
getURL(); 获得您所连接的 URL 名称。
getDriverName(); 获得您所连接的数据库驱动程序的名称。
作者:qs1976
出处:论坛
责任编辑: 方舟
[ 2004-01-31 13:21 ]
数据库是以某种文件结构存储的一系列信息表,这种文件结构使您能够访问这些表、选择表中的列、对表进行排序以及根据各种标准选择行
您可以使用 DataBaseMetaData 的 getTables() 方法来获取数据库中表的信息。这个方法有如下4个 String 参数:
results =dma.getTables(catalog, schema, tablemask, types[]);
其中参数的意义是:
Catalog 要在其中查找表名的目录名。对于 JDBC-ODBC 数据库以及许多其他数据库而言,可将其设置为 null。这些数据库的目录项实际上是它在文件系统中的绝对路径名称。
Schema 要包括的数据库“方案”。许多数据库不支持方案,而对另一些数据库而言,它代表数据库所有者的用户名。一般将它设置为 null。
Tablemask 一个掩码,用来描述您要检索的表的名称。如果您希望检索所有表名,则将其设为通配符 %。请注意,SQL 中的通配符是 % 符号,而不是一般 PC 用户的 * 符号。
types[] 这是描述您要检索的表的类型的 String 数组。数据库中通常包括许多用于内部处理的表,而对作为用户的您没什么价值。如果它是空值,则您会得到所有这些表。如果您将其设为包含字符串“TABLES”的单元素数组,您将仅获得对用户有用的表格。
一个简单的 JDBC 程序
我们已经学习了 JDBC 的所有基本功能,现在我们可以编写一个简单的程序,该程序打开数据库,打印它的表名以及某一表列的内容,然后对该数据库执行查询。此程序如下所示:
package skydevkit; import java.sql.*; public class JdbcOdbc_test { ResultSet results; ResultSetMetaData rsmd; DatabaseMetaData dma; Connection con; public JdbcOdbc_test() throws SQLException { String url = "jdbc:odbc:Northwind"; try { //加载 JDBC-ODBC 桥驱动程序 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); con = DriverManager.getConnection(url);//连接数据库 dma = con.getMetaData();//获取数据库的元数据 System.out.println("Connected to:" + dma.getURL()); System.out.println("Driver " + dma.getDriverName()); } catch (Exception e) { System.out.println(e); } try { Statement stmt = con.createStatement(); results = stmt.executeQuery("select * from 客户;"); ResultSetMetaData resultMetaData = results.getMetaData(); int cols = resultMetaData.getColumnCount(); String resultRow = ""; for (int i = 1; i < cols; i++) { resultRow += resultMetaData.getColumnName(i) + ";"; } System.out.println(resultRow); while (results.next()) { resultRow = ""; for (int i = 1; i < cols; i++) { try { resultRow += results.getString(i) + ";"; } catch (NullPointerException e) { System.out.println(e.getMessage()); } } System.out.println(resultRow); } } catch (Exception e) { System.out.println("query exception"); } finally { results.close(); } } } |
补充高级内容
关于调用SQLServer存储过程的例子:(用到了我们开发的数据库连接类)
CREATE PROCEDURE [dbo].[sp_getStudentByName](@name char(10)) AS Select * from Students where [Name]=@name GO DbObject DbO = new DbObject(new SqlServerConnectionFactory("localhost", 1433, "demo", "sa", "")); Connection con = DbO.getConnection(); CallableStatement pstmt = null; System.out.println("TestDB1()............"); /* try { pstmt = con.prepareCall("{call sp_getStudentById(?)}"); pstmt.setInt(1, 1); }*/ try { pstmt = con.prepareCall("{call sp_getStudentByName(?)}"); //注意参数如何传递 pstmt.setString(1, "Tom"); } …… |
使用输出参数:
CREATE PROCEDURE [dbo].[sp_insertStudent](@name char(10),@age int,@id int OUTPUT) AS insert into Students([Name],[Age]) values (@name,@age) select @id=@@IDENTITY GO try { pstmt = con.prepareCall("{call sp_insertStudent(?,?,?)}"); pstmt.setString(1, "zengqingsong"); pstmt.setInt(2, 22); pstmt.registerOutParameter(3, Types.INTEGER); pstmt.executeUpdate(); int id = pstmt.getInt(3); System.out.println(id); } |
使用返回参数的例子:
CREATE PROCEDURE [dbo].[sp_insertStudent](@name char(10),@age int,@id int OUTPUT) AS insert into Students([Name],[Age]) values (@name,@age) select @id=@@IDENTITY –测试输出参数 return 30 –测试返回30 GO try { pstmt = con.prepareCall("{?=call sp_insertStudent(?,?,?)}"); pstmt.setString(2, "zengqingsong"); pstmt.setInt(3, 22); pstmt.registerOutParameter(4, Types.INTEGER); pstmt.registerOutParameter(1, Types.INTEGER); int ret = pstmt.executeUpdate(); //执行影响的行数 int ret2 = pstmt.getInt(1); //返回参数(输出参数) int id = pstmt.getInt(4); //输出参数 System.out.println(ret); System.out.println(ret2); System.out.println(id); } |