`
sober1988
  • 浏览: 9029 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

全面解析JDBC <二>

阅读更多
下面的代码演示了一种方法用来确认已访问调用方法execute所产生的全部结果集和更新计数:

stmt.execute(queryStringWithUnknownResults);
while(true){
introwCount=stmt.getUpdateCount();
if(rowCount>0){//它是更新计数
System.out.println("Rows changed="+count);
stmt.getMoreResults();
continue;
}
if(rowCount==0){//DDL命令或0个更新
System.out.println("No rows changed or statement was DDL command");
stmt.getMoreResults();
continue;
}
//执行到这里,证明有一个结果集
//或没有其它结果
ResultSet rs=stmt.getResultSet();
if(rs!=null){
...//使用元数据获得关于结果集列的信息
while(rs.next()){
...//处理结果
stmt.getMoreResults();
continue;
}
break;//没有其它结果
如何获得SQL语句的执行结果?

  ResultSet包含符合SQL语句中条件的所有行,并且它通过一套get方法(这些get方法可以访问当前行中的不同列)提供了对这些行中数据的访问。ResultSet.next方法用于移动到ResultSet中的下一行,使下一行成为当前行。

  下面的代码段是执行SQL语句的示例。该SQL语句将返回行集合,其中列1为int,列2为String,而列3则为字节数组:

Java.sql.Statementstmt=conn.createStatement();
ResultSet r=stmt.executeQuery("SELECT a,b,c FROM Table1");
while(r.next()){
//打印当前行的值。
Int i=r.getInt("a");
String s=r.getString("b");
Float f=r.getFloat("c");
System.out.println("ROW="+i+" "+s+" "+f);
}

  1. 行和光标

  ResultSet维护指向其当前数据行的光标。每调用一次next方法,光标向下移动一行。

  最初它位于第一行之前,因此第一次调用next将把光标置于第一行上,使它成为当前行。随着每次调用next导致光标向下移动一行,按照从上至下的次序获取ResultSet行。

  在ResultSet对象或其父辈Statement对象关闭之前,光标一直保持有效。在SQL中,结果表的光标是有名字的。如果数据库允许定位更新或定位删除,则需要将光标的名字作为参数提供给更新或删除命令。可通过调用方法getCursorName获得光标名。

  DatabaseMetaData.supportsPositionedDelete和supportsPositionedUpdate方法来检查特定连接是否支持这些操作。当DBMS支持定位更新和删除操作时,DBMS/驱动程序必须确保适当锁定选定行,以使定位更新不会导致更新异常或其它并发问题。

  2. 列

  方法getXXX提供了获取当前行中某列值的途径。在每一行内,可按任何次序获取列值。但为了保证可移植性,应该从左至右获取列值,并且一次性地读取列值。

  列名或列号可用于标识要从中获取数据的列。例如,如果ResultSet对象rs的第二列名为"title",并将值存储为字符串,则下列任一代码将获取存储在该列中的值:

  String s=rs.getString("title");
  String s=rs.getString(2);

  注意列是从左至右编号的,并且从列1开始。同时,用作getXXX方法的输入的列名不区分大小写。

  提供使用列名这个选项的目的是为了让在查询中指定列名的用户可使用相同的名字作为getXXX方法的参数。另一方面,如果select语句未指定列名(例如在"select * from table1"中或列是导出的时),则应该使用列号。这些情况下,用户将无法确切知道列名。

  有些情况下,SQL查询返回的结果集中可能有多个列具有相同的名字。如果列名用作getXXX方法的参数,则getXXX将返回第一个匹配列名的值。因而,如果多个列具有相同的名字,则需要使用列索引来确保检索了正确的列值。这时,使用列号效率要稍微高一些。

  关于ResultSet中列的信息,可通过调用方法ResultSet.getMetaData得到。返回的ResultSetMetaData对象将给出其ResultSet对象各列的编号、类型和属性。

  如果列名已知,但不知其索引,则可用方法findColumn得到其列号。

  3. 数据类型和转换

  对于getXXX方法,JDBC驱动程序试图将基本数据转换成指定Java类型,

  然后返回适合的Java值。例如,如果getXXX方法为getString,而基本数据库中数据类型为VARCHAR,则JDBC驱动程序将把VARCHAR转换成JavaString。getString的返回值将为JavaString对象。

  4. 对非常大的行值使用流
  ResultSet可以获取任意大的LONGVARBINARY或LONGVARCHAR数据。方法getBytes和getString将数据返回为大的块(最大为Statement.getMaxFieldSize的返回值)。但是,以较小的固定块获取非常大的数据可能会更方便,而这可通过让ResultSet类返回Java.io.Input流来完成。从该流中可分块读取数据。注意:必须立即访问这些流,因为在下一次对ResultSet调用getXXX时它们将自动关闭(这是由于基本实现对大块数据访问有限制)。

  JDBCAPI具有三个获取流的方法,分别具有不同的返回值:

  ?getBinaryStream:返回只提供数据库原字节而不进行任何转换的流。

  ?getAsciiStream返回提供单字节ASCII字符的流。

  ?getUnicodeStream返回提供双字节Unicode字符的流。

  注意:它不同于Java流,后者返回无类型字节并可(例如)通用于ASCII和Unicode字符。下列代码演示了getAsciiStream的用法:

Java.sql.Statementstmt=con.createStatement();
ResultSet r=stmt.executeQuery("SELECT x FROM Table2");
//现在以4K块大小获取列1结果:
byte buff=newbyte[4096];
while(r.next()){
Java.io.InputStream fin=r.getAsciiStream(1);
for(;;){
intsize=fin.read(buff);
if(size==-1){//到达流末尾
break;
}
//将新填充的缓冲区发送到ASCII输出流:
output.write(buff,0,size);
}
}

  5. NULL结果值

  要确定给定结果值是否是JDBC NULL,必须先读取该列,然后使用ResultSet.wasNull
方法检查该次读取是否返回JDBC NULL。

  当使用ResultSet.getXXX方法读取JDBC NULL时,方法wasNull将返回下列值之一:

  (1)Javanull值

  对于返回Java对象的getXXX方法(例如getString、getBigDecimal、getBytes、getDate、getTime、getTimestamp、getAsciiStream、getUnicodeStream、getBinaryStream、getObject等)。

  (2)零值:对于getByte、getShort、getInt、getLong、getFloat和getDouble。

  (3)false值:对于getBoolean。

  6. 可选结果集或多结果集

  通常使用executeQuery(它返回单个ResultSet)或executeUpdate(它可用于任何数据库修改语句,并返回更新行数)可执行SQL语句。但有些情况下,应用程序在执行语句之前不知道该语句是否返回结果集。此外,有些已存储过程可能返回几个不同的结果集和/或更新计数。

  为了适应这些情况,JDBC提供了一种机制,允许应用程序执行语句,然后处理由结果集和更新计数组成的任意集合。这种机制的原理是首先调用一个完全通用的execute方法,然后调用另外三个方法,getResultSet、getUpdateCount和getMoreResults。这些方法允许应用程序一次一个地研究语句结果,并确定给定结果是ResultSet还是更新计数。

  用户不必关闭ResultSet;当产生它的Statement关闭、重新执行或用于从多结果序列中获取下一个结果时,该ResultSet将被Statement自动关闭。
 基于JDBC有哪些数据库通用访问方法?

  1. 通用数据库Bean设计

  本实例中对数据库连接和执行SQL语句等通用数据库操作进行了封装,通过实现DBConnBean和DBQueryBean两个JavaBean来完成上述功能。其中DBConnBean负责Java应用程序和数据库的连接;DBQueryBean提供了一组执行标准SQL的功能,可以实现标准SQL完成的所有功能。其功能代码分别如下所示:

  ① DBConnBean.Java的源代码如下所示:

package dbaccess;
import Java.sql.*;
import Java.util.*;
import Java.io.*;
public class DBConnBean
implements Serializable{

private String DBDriver = "sun.jdbc.odbc.JdbcOdbcDriver";
private String DBHost = "127.0.0.1";
private String DBName = "demo";
private String conp = "jdbc:odbc:db_demo";
private String username = "";
private String password = "";
private boolean xdebug = true;

public Connection con = null;

public String sql = null;

Statement stmt = null;
public ResultSet result = null;
private int affectedRows = 0;

public DBConnBean()
{
xdebug = true;
con = null;
sql = null;
}
public Connection Connect()
throws Exception
{
String msg = null;
try
{
Class.forName(DBDriver).newInstance();
}
catch(Exception e)
{
msg = "加载数据库驱动失败";
if (xdebug) msg += "(驱动'"+DBDriver+"')";
throw new Exception(msg);
}
try
{
String conStr = conp;
con = DriverManager.getConnection(conStr,username,password);
}
catch(SQLException e)
{
msg = "!!数据库连接失败";
if (xdebug)
{
msg += "(错误信息='" + e.getMessage()+"' SQL状态值='" + e.getSQLState()+"' 错误代码='" + e.getErrorCode()+"')";
}
throw new Exception(msg);
}
return con;
}
protected void finalize()
throws Throwable
{
super.finalize();
if (stmt != null) stmt.close();
if (result != null) result.close();
}
//最近一次对数据库查询受影响的行数
public int getAffectedRows()
{
return affectedRows;
}
public Connection getCon()
{
return con;
}
public String getConp()
{
return conp;
}
public String getDBDriver()
{
return DBDriver;
}
public String getDBName()
{
return DBName;
}
public boolean getDebug()
{
return xdebug;
}
public String getPassword()
{
return password;
}
public ResultSet getResult()
{
return result;
}
public String getSql()
{
return sql;
}
public String getUsername()
{
return username;
}
public void over()
throws Throwable
{
finalize();
}
public ResultSet query()
throws Exception
{
result = null;
affectedRows = 0;
if (con == null)
Connect();
if (stmt == null)
stmt = con.createStatement();
if (sql.substring(0,6).equalsIgnoreCase("select"))
{
result = stmt.executeQuery(sql);
}
else
{
affectedRows = stmt.executeUpdate(sql);
}
return result;
}
public ResultSet query(String s)
throws Exception
{
sql = s;
return query();
}
public void setDBDriver(String s)
{
DBDriver = s;
}
public void setDebug(boolean b)
{
xdebug = b;
}
public void setgetConp(String s)
{
conp = s;
}
public void setgetDBName(String s)
{
DBName = s;
}
public void setgetUsername(String s)
{
username = s;
}
public void setPassword(String s)
{
password = s;
}
public void setSql(String s)
{
sql = s;
}
}
② DBQueryBean.Java的源代码如下所示:
package dbaccess;
import Java.sql.*;
import Java.util.*;
import Java.io.*;
import Java.lang.reflect.*;

public class DBQueryBean
implements Serializable
{
DBConnBean dbc;
String sql = null;
int rowcount = 0;
int colcount = 0;
// int limitcount = 0;
Vector result = null;
public String _WATCH = "";


public DBQueryBean()
{
dbc = new DBConnBean();
try {
dbc.Connect();
} catch(Exception e) {
handleException(e);
}
}
protected void finalize()
throws Throwable
{
super.finalize();
if (dbc != null) dbc.over();
if (result != null) result.removeAllElements();
}
public String get(int row, int col)
{
if (result==null || row >= result.size()) return null;
String r[] = (String[])result.elementAt(row);
if (col >= Java.lang.reflect.Array.getLength(r)) return null;
return r[col];
}
public int getAffRows() { return dbc.getAffectedRows(); }
public int getColumncount() {
return colcount;
}
public String[] getRow(int row)
{
if (result==null || row >= result.size()) return null;
return (String [])result.elementAt(row);
/*String ret[] = new String[colcount];
Vector r = (Vector)result.elementAt(row);
for (int i=0; i<colcount; i++)
ret[i] = (String)r.elementAt(i);
return ret;*/
}
public int getRowcount() {
return rowcount;
}
public void handleException(Exception e)
{
_WATCH = e.getMessage();
}
public void init()
{
rowcount = 0;
colcount = 0;
// limitcount = 0;
result = null;
}
public void over()
throws Throwable
{
finalize();
}
public int query(String sql)
{
result = new Vector();
int ret = 0;
try {
ResultSet rs = dbc.query(sql);
if (rs == null)
{
ret = dbc.getAffectedRows();
}
else
{
ResultSetMetaData rm = rs.getMetaData();
colcount = rm.getColumnCount();
while (rs.next())
{
String row[] = new String[colcount];
for (int i=0; i<colcount; i++)
row[i] = rs.getString(i+1);
result.addElement(row);
rowcount++;
}
rs.close(); // to release the resource.
ret = result.size();
}
}
catch(Exception e)
{
handleException(e);
return -1;
}

return ret;
}
}
分享到:
评论

相关推荐

    全面解析JDBC 全面解析JDBC

    全面解析JDBC java JDBC java数据库连接 全面解析JDBC java JDBC java数据库连接 全面解析JDBC java JDBC java数据库连接

    全面解析JDBC(强烈推荐)

    全面解析JDBC .

    全面解析JDBC

    全面解析JDBC全面解析JDBC全面解析JDBC

    全面解析JDBC--连接数据库

    Java数据库连接体系结构是用于Java应用程序连接数据库的标准方法。JDBC对Java程序员而言是API,对实现与数据库连接的服务提供商而言是接口模型。

    全面解析JDBC——不错的资料

    JDBC对Java程序员而言是API,对实现与数据库连接的服务提供商而言是接口模型。作为API,JDBC为程序开发提供标准的接口,并为数据库厂商及第三方中间件厂商实现与数据库的连接提供了标准方法。JDBC使用已有的SQL标准...

    全面解析JDBC(txt)

    很详细的jdbc学习资料哦!大家赶快下载把!

    jdbc全面解析

    JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和...

    jsp应用开发详解.part1(共3 part)

    全书分为6篇共22章,包括JSP应用开发基础、JSP核心语法及实例解析,Servlet技术在JSP开发中的应用、JDBC、基于XML的JSP应用程序以及JSP的完整网站开发实例。本书基于完整的J2EE框架,对JSP编程技术进行了深入而全面...

    jsp应用开发详解.part3(共3 part)

    全书分为6篇共22章,包括JSP应用开发基础、JSP核心语法及实例解析,Servlet技术在JSP开发中的应用、JDBC、基于XML的JSP应用程序以及JSP的完整网站开发实例。本书基于完整的J2EE框架,对JSP编程技术进行了深入而全面...

    jsp应用开发详解.part2(共3 part)

    全书分为6篇共22章,包括JSP应用开发基础、JSP核心语法及实例解析,Servlet技术在JSP开发中的应用、JDBC、基于XML的JSP应用程序以及JSP的完整网站开发实例。本书基于完整的J2EE框架,对JSP编程技术进行了深入而全面...

    JDBC连接数据库

    JDBC连接数据库的全部代码,全面的讲解,深度的解析,将是你不错的选择!

    c/s项目实战之jdbc深入学习

    通过一个C/S项目入手,由浅入深学习jdbc。 不需要有javaweb基础,根据本教程即可彻底搞明白jdbc...然后对jdbc做了较为全面的源码解析,同时帮助理解jdbc的实现原理。 适合jdbc初学者和对jdbc理解不够深入的java程序员。

    oracle+MySQL+jdbc数据库教程

    本课程提供专业的数据库培训,深入解析Oracle和MySQL这两大主流关系型数据库管理系统。学员将学习数据库的基本概念、结构化查询语言(SQL)、以及数据库设计与管理的关键知识。从基础的数据表操作到复杂的事务处理和...

    java面试800题

    《java面试800题(包括java,数据库,前台等,绝对全面)》 Q0027 哪些SQL语句在执行时是自动提交的? 数据定义语言DDL是自动提交的。 Q0028 索引对数据库的影响? 提高查询速度 Q0029 主外键有什么关系? 外键是从...

    26个阿里 Java 开源项目,很全面!

    2. JDBC 连接池、监控组件 Druid Druid是一个 JDBC 组件。1.监控数据库访问性能。2.提供了一个高效、功能强大、可扩展性好的数据库连接池。3.数据库密码加密。4.SQL执行日志。 3. Java 的 JSON 处理器 fastjson ...

    java技术经典面试题-详尽解析版

    java技术经典面试题-详尽解析版,是本人在有基本解析的基础上,又对部分比较抽象的或难以理解的做了补充...加了“我要提问,深入解析,疑点解答”等部分,整体来说还是比较全面和易于理解的,是找工作时用得上的好资料。

Global site tag (gtag.js) - Google Analytics