使用 JDBC 创建数据库对象

JDBC的介绍和连接数据库执行sql语句的流程 一、首先介绍一下什么JDBC 现在的应⽤系统⼤多都离不开数据库,Java程序访问数据库的基本⽅式是通过JDBC。JDBC(Java DataBase Connectivity,Java数据库连接)技术的简称,是⼀种⽤于执⾏SQL语句的Java API。它由⼀组⽤Java编程语⾔编写的类和接⼝组成。这个API由 java.sql.*,javax.sql.* 包中的⼀些... 阅读详情
英文原文

使用 JDBC 创建数据库对象

James W. Cooper
IBM T.J. Watson
研究中心
1998 年 5 月


摘自:Java 1.1 中面向对象编程的原理

 

摘要
本文分析了Java DataBase Connectivity (JDBC),一个在 Java 中以面向对象的方法来连接数据库的技术。它是对 ODBC API 进行的一种面向对象的封装和重新设计,它易于学习和使用,并且它能够使您编写不依赖供应商的代码,用以查询和操纵数据库。JDBC 提供了一些相当低层的方法来存取数据库,同时也在相当高层提供了功能强大的对象来处理数据库。

什么是数据库?
数据库是以某种文件结构存储的一系列信息表,这种文件结构使您能够访问这些表、选择表中的列、对表进行排序以及根据各种标准选择行。数据库通常有多个 索引与这些表中的许多列相关联,所以我们能尽可能快地访问这些表。

在进行计算时,数据库比其它类型的结构更常用。您会发现在员工记录和薪资系统中数据库处于核心地位,在旅行计划系统中以及在产品生产和销售的整个过程中都可以发现数据库。

以员工记录为例,您可以设想一个含有员工姓名、地址、工资、扣税以及津贴等内容的表。让我们考虑一下这些内容可能如何组织在一起。您可以设想一个表包含员工姓名、地址和电话号码。您希望保存的其它信息可能包括工资、工资范围、上次加薪时间、下次加薪时间、员工业绩评定等内容。

这些内容是否应保存在一个表格中?几乎可以肯定不应该如此。不同类别的员工的工资范围可能没有区别;这样,您可以仅将员工类型储存在员工记录表中,而将工资范围储存在另一个表中,通过类型编号与这个表关联。考虑以下情况:

Key
Lastname
SalaryType
SalaryType
Min
Max
1
Adams
2
1
30000
45000
2
Johnson
1
2
45000
60000
3
Smyth
3
3
60000
75000
4
Tully
1
5
Wolff
2

SalaryType 列中的数据引用第二个表。我们可以想象出许多种这样的表,如用于存储居住城市和每个城市的税值、健康计划扣除金额等的表。每个表都有一个主键列(如上面两个表中最左边的列)和若干数据列。在数据库中建立表格既是一门艺术,也是一门科学。这些表的结构由它们的 范式指出。我们通常说表属于第一、第二或第三范式,简称为 1NF、2NF 或 3NF。

第一范式:表中的每个表元应该只有一个值(永远不可能是一个数组)。(1NF)

第二范式:满足 1NF,并且每一个副键列完全依赖于主键列。这表示主键和该行中的剩余表元之间是 1 对 1 的关系。(2NF)

第三范式:满足 2NF,并且所有副键列是互相独立的。任何一个数据列中包含的值都不能从其他列的数据计算得到。(3NF)

现在,几乎所有的数据库都是基于“第三范式 (3NF)”创建的。这意味着通常都有相当多的表,每个表中的信息列都相对较少。

从数据库中获取数据
假设我们希望生成一个包含员工及其工资范围的表,在我们设计的一个练习中将使用这个表。这个表格不是直接存在在数据库中,但可以通过向数据库发出一个查询来构建它。我们希望得到如下所示的一个表:

Name
Min
Max
Adams$45,000.00$60,000.00
Johnson$30,000.00$45,000.00
Smyth$60,000.00$75,000.00
Tully$30,000.00$45,000.00
Wolff$45,000.00$60,000.00

或者,按照工资递增的顺序排序

Name
Min
Max
Tully$30,000.00$45,000.00
Johnson$30,000.00$45,000.00
Wolff$45,000.00$60,000.00
Adams$45,000.00$60,000.00
Smyth$60,000.00$75,000.00

我们发现,获得这些表的查询形式如下所示

SELECT DISTINCTROW Employees.Name, SalaryRanges.Min,
SalaryRanges.Max FROM Employees INNER JOIN SalaryRanges ON Employees.SalaryKey = SalaryRanges.SalaryKey
ORDER BY SalaryRanges.Min;

这种语言称为结构化查询语言,即 SQL (一般读作 "sequel" ),而且它是几乎目前所有数据库都可以使用的一种语言。这几年已颁布了若于 SQL 标准,而且大多数 PC 数据库支持大部分 ANSI 标准。 SQL-92 标准被认为是一种基础标准,而且已更新多次。然而,没有一种数据库可以完美地支持后来的 SQL 版本,而且大多数数据库都提供了多种 SQL 扩展,以支持他们数据库独有的性能。
数据库的种类
由于 PC 已成为主要的办公工具,因此,已开发出在 PC 上的大量流行的数据库,这些数据库都是可以自管理的。它们包括初级数据库,如 Microsoft Works ,还包括更为复杂的数据库,如 Approach 、 dBase 、 Borland Paradox 、 Microsoft Access 和 FoxBase 。

另一类 PC 数据库包括那些可由许多 PC 客户机通过服务器访问的数据库。其中包括 IBM DB/2、Microsoft SQL Server、 Oracle、Sybase、SQLBase 和 XDB。所有这些数据库产品都支持多种相对类似的 SQL 方言,因此,所有数据库最初看起来好象可以互换。当然,它们 不能互换的原因是每种数据库都有不同的性能特征,而且每一种都有不同的用户界面和编程接口。您可能会想,既然它们都支持 SQL,对它们进行的编程也应该相似,但这是绝对错误的,因为每种数据库都使用其自己方式接收 SQL 查询,并使用其自己的方式返回结果。这就自然引出了一种新一代的标准:ODBC

ODBC
如果我们能够以某种方式编写不依赖于特定厂商的数据库的代码,并且能够不改变自己的调用程序即可从这些数据库中得到相同的结果,那将是一件很好的事。如果我们可以仅为所有这些数据库编写一些封装,使它们具有相似的编程接口,这种对数据库编程独立于供应商的特性将很容易实现。

Microsoft 于 1992 年首先尝试了这一技巧,该公司发布了一个规范,称为对象数据库连接性。这被认为是在 Windows 环境下连接所有数据库的答案。与所有软件的第一个版本相同,它也经历了一些发展的困扰,在 1994 年推出了另一个版本,该版本运行速度更快,而且更为稳定。它也是第一个 32 位的版本。另外,ODBC 开始向 Windows 之外的其它平台发展,到目前为止,它在 PC 和工作站领域已十分普遍。几乎每个主要的数据库厂商都提供 ODBC 驱动程序。

然而,ODBC 并不是我们最初想象的灵丹妙药。许多数据库厂商都将 ODBC 作为其标准接口之外的“备选接口”,而且对 ODBC 的编程微不足道。与其它 Windows 编程一样,它包括句柄、指针和选项,使其难以掌握。最后一点,ODBC 不是中立的标准。它由 Microsoft 公司开发,并由该公司不断改进,而微软同时也推出了我们所有人所使用的极具竞争性的软件平台,这使得ODBC的未来难以预测。

什么是 JDBC?
JDBC 是一组首字母缩写,曾经代表 “Java DataBase Connectivity” ,但现在它本身已成为一个商标符号。它是对 ODBC API 进行的一种面向对象的封装和重新设计,它易于学习和使用,并且它真正能够使您编写不依赖厂商的代码,用以查询和操纵数据库。尽管它与所有 Java API 一样,都是面向对象的,但它并不是很高级别的对象集,在本章的剩余部分,我们将提出更高级别的方法。

除 Microsoft 之外,多数厂商都采用了 JDBC,并为其数据库提供了 JDBC 驱动程序;这使您可轻松地真正编写几乎完全不依赖数据库的代码。另外,JavaSoft 和 Intersolv 已开发了一种称为 JDBC-ODBC Bridge 的产品,可使您连接还没有直接的 JDBC 驱动程序的数据库。支持 JDBC 的所有数据库必须至少可以支持 SQL-92 标准。这在很大程度上实现了跨数据库和平台的可移植性。

安装和使用 JDBC
JDBC 的类都被归到 java.sql 包中,在安装 Java JDK 1.1 或更高版本时会自动安装。然而,如果您想使用 JDBC-ODBC 桥,还必须安装两个另外的程序包。首先,如果您使用 Windows 95 ,则必须将您的 ODBC 驱动程序升级为 32 位驱动程序,您可从 Microsoft 的网站下载。这个驱动程序在 Microsoft 的网站上很难找到;请搜索 DataAcc.exe 并进行下载和安装。

JDBC-ODBC 驱动程序可从 Sun 的 Java 网站 (http://java.sun.com) 轻松地找到并下载。在您扩充并安装了这个驱动程序后,必须执行下列步骤:

  1. 将 /jdbc-odbc/classes; 路径添加到您的 PATH 环境变量中。
  2. 将 /jdbc-odbc/classes; 路径添加到您的 CLASSPATH 环境变量中。
  3. 在 Windows 95 环境下,将它们放入 autoexec.bat 文件中,重新引导,以使所有设置生效。
  4. 在 Windows NT 环境下,将它们添加到“控制面板”中“系统”对象的“环境”选项卡中,退出并重新登录,以使其生效。
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 代码访问数据库
现在,我们将开始看一下如何编写 Java 程序来访问数据库。我们要使用的数据库是一个称为 groceries.mdb 的 Microsoft Access 数据库。此数据库中的数据由三个本地杂货店中一些常见商品的价格组成。食品表如下所示:

FoodKey
FoodName
1Apples
2Oranges
3Hamburger
4Butter
5Milk
6Cola
7Green beans

杂货店表如下所示:

StoreKey
StoreName
1Stop and Shop
2Village Market
3Waldbaum's

杂货店定价表仅由这三个表格中的键值和价格组成:

FSKey
StoreKey
FoodKey
Price
111$0.27
221$0.29
331$0.33
412$0.36
522$0.29
632$0.47
713$1.98
823$2.45
933$2.29
1014$2.39
1124$2.99
1234$3.29
1315$1.98
1425$1.79
1535$1.89
1616$2.65
1726$3.79
1836$2.99
1917$2.29
2027$2.19
2137$1.99

用 ODBC 注册您的数据库
在 Windows 95 或 NT 环境下访问 ODBC 数据库之前,必须使用控制面板中的 ODBC 驱动程序对它进行注册。在 Windows 95 环境下,就是 “ 控制面板 ” 程序中的 ODBC 图标。在 Windows NT 环境下,您会在 “ 开始 ” 菜单中找到此程序。(如果找不到,您需要安装上述的 ODBC 驱动程序,即 WX1350.exe )。

双击 ODBC 图标,然后单击“添加”,如图 1 所示。然后选择数据库驱动程序(此处使用 Microsoft Access),然后单击“确定”。在“数据源名”和“描述”中分别键入数据源名称 (Groceries) 和数据库说明 (Grocery prices)(这两项都不需要和文件名相关),然后单击“选取”,找到数据库,并选择该数据库。找到该数据库后,屏幕将如图 2 所示。单击“确定”,然后单击“关闭”来关闭面板。


ODBC Data Source Administrator
图 1:ODBC 控制面板设置屏幕。


ODBC Microsoft Access 97 安装
图 2:在 ODBC 控制面板中选择数据库和说明。


连接数据库
所有与数据库有关的对象和方法都在 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
访问数据库
一旦连接到数据库,就可以请求表名以及表列的名称和内容等信息,而且您可以运行 SQL 语句来查询数据库或者添加或修改其内容。可用来从数据库中获取信息的对象有:

DatabaseMetaData有关整个数据库的信息:表名、表的索引、数据库产品的名称和版本、数据库支持的操作。
ResultSet关于某个表的信息或一个查询的结果。您必须逐行访问数据行,但是您可以任何顺序访问列。
ResultSetMetaData 有关 ResultSet 中列的名称和类型的信息。

尽管每个对象都有大量的方法让您获得数据库元素的极为详细的信息,但在每个对象中都有几种主要的方法使您可获得数据的最重要信息。然而,如果您希望看到比此处更多的信息,建议您学习文档以获得其余方法的说明。

ResultSet
ResultSet 对象是 JDBC 中最重要的单个对象。从本质上讲,它是对一个一般宽度和未知长度的表的一种抽象。几乎所有的方法和查询都将数据作为 ResultSet 返回。 ResultSet 包含任意数量的命名列,您可以按名称访问这些列。它还包含一个或多个行,您可以按顺序自上而下逐一访问。在您使用 ResultSet 之前,必须查询它包含多少个列。此信息存储在 ResultSetMetaData 对象中。

 

//从元数据中获得列数
    ResultSetMetaData rsmd;
    rsmd = results.getMetaData();
    numCols = rsmd.getColumnCount();

当您获得一个 ResultSet 时,它正好指向第一行之前的位置。您可以使用 next() 方法得到其他每一行,当没有更多行时,该方法会返回 false。由于从数据库中获取数据可能会导致错误,您必须始终将结果集处理语句包括在一个 try 块中。

try
{
rsmd = results.getMetaData();
numCols = rsmd.getColumnCount();
boolean more = results.next();
while (more)
 {
 for (i = 1; i <= numCols; i++)
 System.out.print(results.getString(i)+" ");
 System.out.println();
 more = results.next();
 }
results.close();
}
catch(Exception e)
{System.out.println(e.getMessage());}
您可以多种形式获取 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”的单元素数组,您将仅获得对用户有用的表格。

用于从数据库中获取表名的简单代码相当于获取 DatabaseMetaData 对象,并从其中检索表名:

con = DriverManager.getConnection(url);
//获取数据库的元数据
dma =con.getMetaData();
//将数据库中的表的名称转储出来
String[] types = new String[1];
types[0] = "TABLES"; //设置查询类型
//请注意通配符是 % 符号(而不是“*”)
results = dma.getTables(null, null, "%", types);

然后,我们可以打印出表名,正如我们上面所做的那样:

boolean more = results.next();
while (more)
 {
 for (i = 1; i <= numCols; i++)
 System.out.print(results.getString(i)+" ");
 System.out.println();
 more = results.next();
 }
如前文所述,将所有代码包括在 try 块中。
执行 SQL 查询
我们已经理解了 JDBC 的基本对象,现在就可以执行 SQL 查询了。查询是作为 Statement 对象的方法执行的,您很容易从 Connection 对象获得 Statement 对象:
String query = "SELECT FoodName FROM Food;";
ResultSet results;
try
 {
 Statement stmt = con.createStatement();
 results = stmt.executeQuery(query);
 }
 catch (Exception e)
 {System.out.println("query exception");}
请注意,这个简单的查询返回 Food 表中的整个 FoodName 列。您使用像这样的简单查询获取整个列的内容。请注意,查询的查询本身是一个 ResultSet ,您可以用我们上面刚讨论过的方法对它进行处理。
打印 ResultSet
因为我们总是要从 ResultSets 中打印数据,我们可以设计一种简单的方法,将整个 ResultSet 转储出来,包括表名称元数据。该子程序如下所示:
private void dumpResults(String head)
{
//这是打印列标头和每列的内容的
//通用方法
System.out.println(head);
 try
 {
 //从元数据中获取列数
 rsmd = results.getMetaData();
 numCols = rsmd.getColumnCount();
 //打印列名
 for (i = 1; i<= numCols; i++)
 System.out.print(rsmd.getColumnName(i)+" ");
 System.out.println();
 //打印列内容
 boolean more = results.next();
 while (more)
 {
 for (i = 1; i <= numCols; i++)
 System.out.print(results.getString(i)+" ";
 System.out.println();
 more = results.next();
 }
 }
catch(Exception e)
 {System.out.println(e.getMessage());}
}

一个简单的 JDBC 程序
我们已经学习了 JDBC 的所有基本功能,现在我们可以编写一个简单的程序,该程序打开数据库,打印它的表名以及某一表列的内容,然后对该数据库执行查询。此程序如下所示:
import java.net.URL;
import java.sql.*;
import java.util.*;
class JdbcOdbc_test
{
 ResultSet results;
 ResultSetMetaData rsmd;
 DatabaseMetaData dma;
 Connection con;
 int numCols, i;
//--
public JdbcOdbc_test()
{
String url = "jdbc:odbc:Grocery prices";
String query = "SELECT DISTINCTROW FoodName FROM Food " + "WHERE (FoodName like 'C%');";
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());
//将数据库中的表的名称转储出来
 String[] types = new String[1];
 types[0] = "TABLES";
 //请注意通配符是 % 符号(而不是“*”)
 results = dma.getTables(null, null, "%", types);
 dumpResults("--Tables--");
 results.close();
 }
 catch (Exception e)
 {System.out.println(e);}
//获取表列的名称
System.out.println("--Column Names--");
try {
 results =
 dma.getColumns(null, null, "FoodPrice", null);
 ResultSetMetaData rsmd = results.getMetaData();
 int numCols = rsmd.getColumnCount();
 while (results.next() )
 String cname = results.getString("COLUMN_NAME");
 System.out.print(cname + " ");
 System.out.println();
 results.close();
 }
catch (Exception e)
 {System.out.println(e);}
//列出一个列的内容 -- 这是一个查询
try {
 Statement stmt = con.createStatement();
 results =
 stmt.executeQuery("SELECT FOODNAME FROM FOOD;");
 }
 catch (Exception e)
 {System.out.println("query exception");}
 dumpResults("--Contents of FoodName column--");
 //尝试实际的 SQL 语句
 try
 {
 Statement stmt = con.createStatement();
 results = stmt.executeQuery(query);
 }
 catch (Exception e)
 {System.out.println("query exception");}
 dumpResults("--Results of Query--");
}
该程序打印出的结果如下所示:
C:/Projects/objectJava/chapter19>java JdbcOdbc_test
Connected to:jdbc:odbc:Grocery prices
Driver JDBC-ODBC Bridge (ODBCJT32.DLL)
--Tables--
TABLE_QUALIFIER TABLE_OWNER TABLE_NAME TABLE_TYPE REMARKS
groceries null Food TABLE null
groceries null FoodPrice TABLE null
groceries null Stores TABLE null
--Column Names--
FSKey StoreKey FoodKey Price
--Contents of FoodName column--
FOODNAME
Apples
Oranges
Hamburger
Butter
Milk
Cola
Green beans
--Results of Query--
FoodName
Cola
构建更高级别的 JDBC 对象
从上面的例子可以明显看出,如果可以将我们使用过的一些方法封装在几个更高级别对象中,那将非常有帮助,我们不仅可以封装 try 程序块,而且可以更简单地访问 ResultSet 方法。

在这一部分中,我们将构建一个新的 resultSet 对象,该对象封装了 JDBC ResultSet 对象,并以 String 数组的形式返回一行数据。我们发现您始终需要从 ResultSetMetaData 对象中获取列的序号和名称,因此,创建一个封装元数据的新对象就非常合理。

另外,我们经常需要按名称或整数索引提取某行的元素,如果不必总是将这些访问语句包括 try 块中,那将大有帮助。最后一点,如果我们需要整行的内容,则更方便的做法是将整行以String 数组形式返回。在下面所示的 resultSet 对象中,我们致力于实现这些目标:

class resultSet
{
//这个类是 JDBC ResultSet 对象的更高级抽象
 ResultSet rs;
 ResultSetMetaData rsmd;
 int numCols;
 public resultSet(ResultSet rset)
 {
 rs = rset;
 try
 {
 //同时获取元数据和列数
 rsmd = rs.getMetaData();
 numCols = rsmd.getColumnCount();
 }
 catch (Exception e)
 {System.out.println("resultset error"
 +e.getMessage());}
 }
 //--
 public String[] getMetaData()
 {
 //返回包含所有列名或其他元数据的
 //一个数组
 String md[] = new String[numCols];
 try
 {
 for (int i=1; i<= numCols; i++)
 md[i-1] = rsmd.getColumnName(i);
 }
 catch (Exception e)
 {System.out.println("meta data error"+
 e.getMessage());}
 return md;
 }
 //--
 public boolean hasMoreElements()
 {
 try{
 return rs.next();
 }
 catch(Exception e){return false;}
 }
 //--
 public String[] nextElement()
 {
 //将行的内容复制到字符串数组中
 String[] row = new String[numCols];
 try
 {
 for (int i = 1; i <= numCols; i++)
 row[i-1] = rs.getString(i);
 }
 catch (Exception e)
 {System.out.println("next element error"+
 e.getMessage());}
 return row;
 }
 //--
 public String getColumnValue(String columnName)
 {
 String res = "";
 try
 {
 res = rs.getString(columnName);
 }
 catch (Exception e)
 {System.out.println("Column value error:"+
 columnName+e.getMessage());}
 return res;
 }
 //--
 public String getColumnValue(int i)
 {
 String res = "";
 try
 {
 res = rs.getString(i);
 }
 catch (Exception e)
 {System.out.println("Column value error:"+
 columnName+e.getMessage());}
 return res;
 }
 //--
 public void finalize()
 {
 try{rs.close();}
 catch (Exception e)
 {System.out.println(e.getMessage());}
 }
}
通过简单使用 new 操作符就地创建一个 ResultSet 对象,我们很容易将任何 ResultSet 对象封装在此类中:
ResultSet results = .. //按通常的方法获得ResultsSet
//利用它创建一个更有用的对象
resultSet rs = new resultSet(results);
并很容易在任何 JDBC 程序中使用这个对象。
构建一个 Database 对象
我们沿 00 链向上移的另一部分努力是创建一个 Database 对象,它将封装下列对象的行为: Connection 、 Statement 和 DatabaseMetaData 对象, 以及我们刚刚构建的 SQL 查询和 resultSet 。我们的 Database 对象允许我们创建连接、获取表名、在数据库中移动以及更简单地获得行和列的值。请注意, Execute 方法返回一个 resultSet 对象,您可以直接对它进行操作。
class Database
{
//这是一个将 JDBC 数据库的所有功能封装在单个对象中的类
Connection con;
resultSet results;
ResultSetMetaData rsmd;
DatabaseMetaData dma;
String catalog;
String types[];
 public Database(String driver)
 {
 types = new String[1];
 types[0] = "TABLES"; //初始化类型
 try{Class.forName(driver);} //加载 JDBC-ODBC 桥驱动程序
 catch (Exception e)
 {System.out.println(e.getMessage());}
 }
 //--
 public void Open(String url, String cat)
 {
 catalog = cat;
 try {con = DriverManager.getConnection(url);
 dma =con.getMetaData(); //获取元数据
 }
 catch (Exception e)
 {System.out.println(e.getMessage());}
 }
 //--
 public String[] getTableNames()
 {
 String[] tbnames = null;
 Vector tname = new Vector();
 //将表名添加到一个 Vector 中,
 //因为我们不知道有多少个表
 try {
 results =
 new resultSet(dma.getTables(catalog, null,
 "%", types));

 while (results.hasMoreElements())
 tname.addElement(results.getColumnValue("TABLE_NAME"));

 }
 catch (Exception e) {System.out.println(e);}
 //将表名复制到一个 String 数组中
 tbnames = new String[tname.size()];
 for (int i=0; i< tname.size(); i++)
 tbnames[i] = (String)tname.elementAt(i);
 return tbnames;
 }
 //--
 public String[] getTableMetaData()
 {
 // 返回表类型的信息
 results = null;
 try{
 results =
 new resultSet(dma.getTables(catalog, null,
 "%", types));
 }
 catch (Exception e)
 {System.out.println(e.getMessage());}
 return results.getMetaData();
 }
 //--
 public String[] getColumnMetaData(String tablename)
 {
 //返回一个列的数据
 results = null;
 try {
 results =
 new resultSet(dma.getColumns(catalog, null,
 tablename, null));
 }
 catch (Exception e)
 {System.out.println(e.getMessage());}
 return results.getMetaData();
 }
 //--
 public String[] getColumnNames(String table)
 {
 //返回一个列名数组
 String[] tbnames = null;
 Vector tname = new Vector();
 try {
 results =
 new resultSet(dma.getColumns(catalog, null,
 table, null));
 while (results.hasMoreElements() )
 tname.addElement(results.getColumnValue("COLUMN_NAME"));
 }
 catch (Exception e) {System.out.println(e);}
 tbnames = new String[tname.size()];
 for (int i=0; i< tname.size(); i++)
 tbnames[i] = (String)tname.elementAt(i);
 return tbnames;
 }
//--
public String getColumnValue(String table,
 String columnName)
 {
 //返回给定列的值 String res = null;
 try
 {
 if (table.length()>0)
 results =
 Execute("Select " + columnName +
 " from " + table +
 " order by "+columnName);
 if (results.hasMoreElements())
 res = results.getColumnValue(columnName);
 }
 catch (Exception e)
 {System.out.println("Column value error" +
 columnName+ e.getMessage());}
 return res;
 }
//--
 public String getNextValue(String columnName)
 {
 // 使用存储的 resultSet
 //返回该列的下一个值
 String res = "";
 try
 {
 if (results.hasMoreElements())
 res = results.getColumnValue(columnName);
 }
 catch (Exception e)
 {System.out.println("next value error"+
 columnName+ e.getMessage());}
 return res;
}
//--
 public resultSet Execute(String sql)
 {
 //对此数据库执行一个 SQL 查询
 results = null;
 try
 {
 Statement stmt = con.createStatement();
 results = new resultSet(stmt.executeQuery(sql));
 }
 catch (Exception e)
 {System.out.println("execute error"+
 e.getMessage());}
 return results;
 }
}
一个可视化的数据库程序
为了对我们本章学习的内容进行总结,我们编写一个简单的 GUI 程序,它可以显示数据库的表名、列名和列内容。我们还将包括一个文本区域,您可以在其中键入一个要对数据库执行的 SQL 查询。在 Companion CD-ROM 上的 /chapter20 子目录中,可以找到本程序(称为 dbFrame.java )所使用的 resultSet 和 Database 类。程序的显示界面如图 3 所示。

数据库图示
图 3:用来显示用 JDBC 连接的数据库中的数据的 dbFrame.java 程序。

在本程序中,默认数据库 (groceries.mdb) 的表名显示在左侧的栏中。当您单击其中一个表名时,列名就会显示在中间的栏中。最后,当您单击中间栏中的某一行时,该行的内容就会显示在右侧的栏中。

本程序的关键只是接收列表选择,然后清除并填充正确的列表框:

public void itemStateChanged(ItemEvent e)
 {
 Object obj = e.getSource();
 if (obj == Tables) //放入列名
 showColumns();
 if (obj == Columns) //放入列的内容
 showData();
 }
//--
 private void loadList(List list, String[] s)
 {
 //清除并填充指定的列表框
 list.removeAll();
 for (int i=0; i< s.length; i++)
 list.add(s[i]);
 }
 //--
 private void showColumns()
 {
 //显示列名
 String cnames[] =
 db.getColumnNames(Tables.getSelectedItem());
 loadList(Columns, cnames);
 }
 //--
 private void showData()
 {
 String colname = Columns.getSelectedItem();
 String colval =
 db.getColumnValue(Tables.getSelectedItem(),
 colname);
 Data.setVisible(false);
 Data.removeAll();
 Data.setVisible(true);
 colval =
 db.getNextValue(Columns.getSelectedItem());
 while (colval.length()>0)
 {
 Data.add(colval);
 colval =
 db.getNextValue(Columns.getSelectedItem());
 }
 }
执行查询
显示画面底部的文本区域使您可键入所需的任何 SQL 查询。演示程序中构建的一个查询如下所示:
String queryText =
"SELECT DISTINCTROW FoodName, StoreName, Price "+
"FROM (Food INNER JOIN FoodPrice ON "+
"Food.FoodKey = FoodPrice.FoodKey) " +
"INNER JOIN Stores ON "+
"FoodPrice.StoreKey = Stores.StoreKey "+
"WHERE (((Food.FoodName)=/'Oranges/')) "+
" ORDER BY FoodPrice.Price;";
此查询简单地列出每个杂货店的桔子价格。

当您单击 Run Query 按钮时,它将执行此查询,并将 resultSet 对象传送给一个对话框进行显示:

public void actionPerformed(ActionEvent e)
 {
 Object obj = e.getSource();
 if (obj == Quit)
 System.exit(0);
 if (obj == Search)
 clickedSearch();
 }
//--
 private void clickedSearch()
 {
 resultSet rs = db.Execute(query.getText());
 String cnames[] = rs.getMetaData();

 queryDialog q = new queryDialog(this, rs);
 q.show();
 }
查询结果对话框
查询对话框获得 resultSet 对象,并将每一行放入一个 String 数组中,然后将这些 String 数组放入一个 Vector 中,这样就可以在 paint() 子程序运行期间快速访问这些行。
private void makeTables()
{
//将每一行放入一个 String 数组中,并将
//这些字符串数组全部放入一个 Vector 中
 tables = new Vector();
 String t[] = results.getMetaData();
 tables.addElement( t);
 while (results.hasMoreElements())
 tables.addElement(results.nextElement());
 }
我们通过 Graphics 的 drawString() 方法将数据绘制在一个 Panel 中。就像在 Printer 对象中一样,我们必须自己跟踪 x 和 y 的位置。
public void paint(Graphics g)
{
String s[];
int x=0;
//计算字体的高度
int y =g.getFontMetrics().getHeight();
//估算列的高度
int deltaX = (int)1.5f*
 (g.getFontMetrics().stringWidth("wwwwwwwwwwwwww"));
//遍历表矢量
for (int i=0; i< tables.size(); i++)
 {
 s = (String[])tables.elementAt(i);
 //绘制字符串数组中的每一行
 for (int j =0; j< s.length; j++)
 {
 String st= s[j];
 g.drawString(st, x, y);
 x += deltaX; //移到下一列
 }
 x = 0; //开始一个新行
 y += g.getFontMetrics().getHeight();
 //列标签与列数据之间的额外空间
 if (i == 0) y += g.getFontMetrics().getHeight();
 }
}
内建查询的 queryDialog 如图 4 所示。

查询结果
图 4:dbFrame 程序中 显示的 queryDialog,其中显示的是默认查询的结果。

示例文件
groceries.zip
dbFrame.zip
jdbc-odbc Bridge
小结
在本文中,我们讨论了数据库以及检验数据库并对数据库执行查询的方法。我们已经看到, JDBC 提供了一种与平台和数据库无关的、面向对象的方法来访问这些数据,我们还学习了 JDBC 的主要对象: ResultSet 、 ResultSetMetaData 和 DatabaseMetaData。 在用这些对象编写了一个简单的程序之后,我们设计了更高级别的 resultSet 和 Database 对象,我们用它们构建了一个简单的可视化界面来显示数据库信息。

如果您熟悉数据库的强大功能,就会认识到 SQL 语言可使您执行比我们此处所述操作更强大的任务。例如,您可以创建新表、添加、更改或删除表的行、列或单个表元。使用 JDBC,所有这一切都变得通用和易于处理。

如果您使用的是特定平台的数据库驱动程序,如 JDBC-ODBC Bridge,则您在编写应用程序时会受到限制,因为 applet 不能连接在另一台计算机上运行的这个桥。其他客户机-服务器数据库,如 IBM 的 DB2,允许您使用 applet 中的 JDBC 与其连接。


要了解本网站上有关 Java 和数据库连接性的更多信息,请访问: http://www.cnet.com/Content/Builder/Programming/Databases/?st.bl.fd.prog1.feat

使用JDBC连接MySQL数据库--典型案例分析(七)----批量插入员工信息 转载请注明:张奇的优快云博客 - 博客频道 - youkuaiyun.com 问题: 向Emp表中批量插入100条数据,需要插入数据的列为empno,ename以及sal.这三个字段对应的数据分别为empno列的数据通过序列emp_seq自动生成,ename列的数据为字符串 "name"+循环次数i组成、sal的数据有随机生成的10000以内的整数构成。 方案: 每循环一次,向数据库插入一条 阅读详情

相关推荐

掌握JDBC创建数据库的完整流程

数据库连接是任何数据库操作的起点。没有它,应用程序无法与数据库服务器通信,从而无法执行CRUD(创建、读取、更新、删除)等基本操作。一个稳定且高效的数据库连接是确保系统性能和数据一致性的关键。

weixin_42126677的博客 692

使用 JDBC 创建数据库对象 1

本文分析了Java DataBase Connectivity (JDBC),一个在 Java 中以面向对象的方法来连接数据库的技术。它是对 ODBC API 进行的一种面向对象的封装和重新设计,它易于学习和使用,并且它能够使您编写不依赖供应商的代码,用以查询和操纵数据库。JDBC 提供了一些相当低层的方法来存取数据库,同时也在相当高层提供了功能强大的对象来处理数据库。 什么是数据库?

wxyxl的专栏 1705

VASPKIT绘制平面平均电荷差分密度

平面平均密度差(planar-averaged electron density difference)是密度差的衍生。密度差是个三维空间函数,经常通过绘制平面图、等值面图方式图形化考察。虽然这两种图很直观,但平面图会受到截面选取的影响,而等值面图会受到等值面数值(isovalue)选取的影响,因此都有一定任意性,也不容易定量讨论。对于电子转移有比较明确方向的情况,可以绘制平面平均密度差曲线,由此可以清楚地考察垂直于选取的方向上每个截面上的密度差积分值,在定量讨论、对比上比较便利。

weixin_43948934的博客 1万+

JDBC连接数据库以及工具类创建

使用JDBC连接数据库,以及创建一个链接数据库的工具类

好看的皮囊千篇一律,有趣的灵魂万里挑一。 1448

Android车载应用开发与分析(11)- 车载Android应用开发入门指南

将时间回退到2017年我大学刚毕业时,彼时移动互联网就已经开始退潮,各大个培训机构也纷纷停止了Android相关的培训,曾经热火朝天的应用开发从那时起,就开始走向下坡路,小程序以及众多跨平台框架也让市场对Android原生开发的需求逐年降低,市场需求的降低也造就了Android开发的面试变得史无前例的“卷”。 终于我在2019年选择离开了互联网,投身当时还不是非常火热的车载Android领域继续从事Android原生开发。而这一年中国首个外商独资的整车制造项目,“...

linkwj的博客 1万+

2024.6.10丨基于DIAMOND与VFDB数据库的致病菌毒力因子高效注释指南

本文详细介绍了基于DIAMOND与VFDB数据库的致病菌毒力因子高效注释方法,涵盖工具安装、参数优化、数据库选择及实战案例解析。通过DIAMOND的快速比对和VFDB的全面毒力因子数据,显著提升微生物基因组研究效率,适用于临床检测、食品安全监测等多个场景。

weixin_33712987的博客 376

jdbc连接(没有面向对象)

jdbc的概念 java database connection(就是java和数据库连接) 完成这个需要用到的工具(idea(编写代码)和SQLyog(mysql)),所以需要安装idea,mysql数据库和SQLyog 一般完成jdbc需要七个步骤 1.加载驱动 2.创建连接 3.编写sql语句 4.执行sql语句 5.得到结果集 6.处理结果 7.关闭连接 下面进行具体的实例 项目完成前需要...

xiaobai_shiro的博客 202

别再纠结VS还是VSCode了!新手C#环境搭建保姆级指南(含.NET Core安装验证)

本文为C#新手提供Visual Studio与VS Code的深度对比及环境搭建指南,涵盖.NET Core安装验证、工具选择决策框架及实战配置技巧。帮助开发者根据项目需求选择合适工具,快速搭建高效开发环境,提升编码效率。

weixin_30455023的博客 561

详细版的JDBC连接数据库(包括数据库的建立)

首先新建一个连接,我这里已经写好了,我使用的是localhost,用户名:root。3.我们直接用代码实现吧,这里我MySQL用的是HeisiSQL。建完表以后就是建立表的属性信息,也可以查询里面用代码写。建立表里面的相关属性信息代码是这样子的。2.JDBC的常用API。进去之后就是新建数据库了。

m0_52873654的博客 582

基于matlab版本的三维直流电法反演算法

可以使用RESINVM3D工具包等现成的MATLAB工具进行三维直流电法反演。反演问题求解:基于MATLAB的反演问题求解算法实现和应用,包括反演问题数值模拟、反演问题参数优化和反演问题结果分析。希望这个代码示例能帮助你入门三维直流电法反演。如果有更具体的需求或问题,可以进一步探讨。反演过程中可能需要调整正则化参数和优化算法的设置。需要根据实际问题实现,可能涉及复杂的数值计算。

ytttr873的博客 668

调用D3D11硬解码和渲染VideoProcessor版本

在https://blog.youkuaiyun.com/robothn/article/details/78781321一文中使用shader来显示FFMPEG硬解码后的YUV420P,本文调用D3D11的videoprocessor来进行图像空间变换和尺寸变换,取得了较好的效果。 1.初始化D3D11设备、videodevice等数据结构 FFMPEG调用D3D11硬解码,获取其对应的device,videodevice。。。 FFMPEG使用av_hwdevice_find_type_by_name调用D3d11

zlyadvocate的博客 9285

使用JDBC创建数据库对象

摘要 本文分析了Java DataBase Connectivity (JDBC),一个在 Java 中以面向对象的方法来连接数据库的技术。它是对 ODBC API 进行的一种面向对象的封装和重新设计,它易于学习和使用,并且它能够使您编写不依赖供应商的代码,用以查询和操纵数据库。JDBC 提供了一些相当低层的方法来存取数据库,同时也在相当高层提供了功能强大的对象来处理数据库。 什么是数据库? 数据

303

51单片机嵌入式开发:14、STC89C52RC 之HX1838红外解码NEC+数码管+串口打印+LED显示

对于C51单片机的设计思路,你可以使用类似的步骤来实现红外解码、数码管显示和LED显示的功能。下面是一个简单的设计思路:(1) 连接HX1838红外解码器、数码管和LED到C51单片机。将HX1838的信号引脚连接到C51单片机的外部中断引脚(例如INT0),数码管的CLK引脚连接到C51单片机的某个IO口引脚,数码管的DIO引脚连接到C51单片机的另一个IO口引脚,LED连接到C51单片机的某个IO口引脚。(2) 在C51的程序中,定义并初始化所需的IO口和外部中断。

sinat_30943509的博客 2977

使用 JDBC 创建数据库对象 2

构建更高级别的 JDBC 对象从上面的例子可以明显看出,如果可以将我们使用过的一些方法封装在几个更高级别对象中,那将非常有帮助,我们不仅可以封装 try 程序块,而且可以更简单地访问 ResultSet 方法。 在这一部分中,我们将构建一个新的 resultSet 对象,该对象封装了 JDBC ResultSet 对象,并以 String 数组的形式返回一行数据。我们发现您始终需要从 Re

wxyxl的专栏 1103

Adams Car——Adams car与Simulink联合仿真

Adams与simulink悬架联合仿真

Mr.邹的博客 2127

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

[转载]使用JDBC创建数据库对象

使用JDBC创建数据库对象摘要 本文分析了Java DataBase Connectivity (JDBC),一个在 Java 中以面向对象的方法来连接数据库的技术。它是对 ODBC API 进行的一种面向对象的封装和重新设...

congji3817的博客 444

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Java数据库连接(Java Database Connectivity,JDBC)

第一个jdbc程序 回到顶部 JDBC简介 Java数据库连接(Java Database Connectivity,JDBC),是一种用于执行SQL语句的Java API,它由一组用Java编程语言编写的类和接口组成。 JDBC为数据库开发人员提供了一个标准的API,使他们能够用纯Java API来编写数据库应用程序。 使用JDBC编写的程序能够自动地将SQL语句传送给

词语大杂烩 2540

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

1、JDBC连接数据库步骤(六个步骤)

1.注册驱动: Class.forName("com.mysql.jdbc.Driver");显示的加载到JVM中 2.获取连接: (1) 要连接数据库的url---- String url="jdbc:mysql://localhost:3306/test?"+ "useUnicode=true&characterEncoding=UTF8";//防止乱码 要连接数据库的用户名---- String user="xxxx"; 要连接数据库的密码---- String pass="xxxx";

you can you up up up的博客 2万+

JavaWeb——教你写db数据库连接类

db连接类 db就是database(数据库),下面我讲演示如何通过java语言通过jdbc的方式来连接到你所要的数据库,本例中以oracle为参考。 代码实现首先我们先创造几个等会会用到的对象 创造一个数据库连接对象(Connection对象,代表与数据源进行的唯一会话。)。 创建编译语句对象(Statement对象,建立了到特定数据库的连接之后,就可用该连接发送 SQL 语句。)。 创建预编

流浪~ 6605

创建mysql对象_mysql创建statement对象

mysql创建statement对象关注:56答案:4mip版解决时间 2021-01-24 21:05提问者西伯利亚狼2021-01-24 13:31package com.yxq.toolsbean;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java...

weixin_33208553的博客 739

使用JDBC操作MySQL数据库

什么是JDBC JDBC是Java数据库连接,(Java Database Connectivity)的简称,是Java语言中用来规范客户端程序如何来访问关系型数据库的应用程序接口,提供了诸如增加,删除,修改,查询据库中数据的方法。 JDBC连接数据库的步骤 下面以MySQL为例,介绍一下JDBC连接数据库的步骤。 1.加载数据库驱动程序 Class.forName(“com.mysql.jdbc.Driver”); 2.定义要连接数据库的连接地址URL,地址URL的格式为:jdbc:<子协

xiaolichaoren的博客 646
上一篇: JDK 1.4 中打印,
下一篇: 好的资源
lwqadmin
博客等级 码龄22年 6粉丝 92原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值