分享
 
 
 

使用 JDBC 创建数据库对象 2

王朝java/jsp·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

构建更高级别的 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

DataAcc.exe--

jdbc-odbc Bridge

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

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

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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有