课外天地 李树青学习天地Java程序语言课件 → 课件21下载——JDBC


  共有15254人关注过本帖树形打印复制链接

主题:课件21下载——JDBC

帅哥哟,离线,有人找我吗?
admin
  1楼 博客 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信 管理员
等级:管理员 帖子:1940 积分:26616 威望:0 精华:34 注册:2003/12/30 16:34:32
课件21下载——JDBC  发帖心情 Post By:2006/2/26 22:09:21 [只看该作者]

1 简介
Java的JDBC是Java应用访问数据库的通用编程接口,一个紧凑、简单的软件层,主要功能在于定义了应用程序如何打开数据库连接、如何与数据库通信、如何执行SQL语句和如何检索查询结果等,同时兼顾了通用性、速度和兼容性,即
1)通用:跨数据库、跨平台,通过对不同的数据库的客户端的抽象,提供统一的编程接口
2)速度:运用不同的JDBC驱动程序,可提高访问数据库的速度。通用性是速度的敌人,从底层实现JDBC接口可以提高速度。oracle thin driver从tcp层实现jdbc接口。所以速度的问题就是采用何种jdbc驱动的问题。
3)兼容性:适应主流数据库产品的通用特征,如是否支持可修改游标,所支持的二进制对象的最大长度是多少,在一个Connection里面能同时支持多少个语句,同时能打开多少个表等。JDBC充分支持兼容性问题。

具体来看,JDBC的特性有:
1)不限制传递到底层DBMS驱动程序的查询类型
2)JDBC机制易于理解和使用
3)提供与Java系统的其他部分保持一致的Java接口
4)JDBC可以在常见SQL层API的顶层实现

同时,JDBC具有SQL一致性,即JDBC在类Java.SQL.Types中定义了一组通用SQL类型标识符,并且JDBC还通过以下几种方式处理SQL一致性问题:JDBC API允许将任何查询字符串传递到底层DBMS驱动程序;提供内置功能,便于将包含转义序列的SQL查询转换为数据库可理解的格式;提供DatabaseMetaData接口,允许用户检索关于所使用的DBMS信息。

JDBC支持两种模型:二层模型和三层模型。二层模型表现为Java applet和应用程序直接与数据库交互,被称为客户端/服务器配置;三层模型
使用中间层,可以在不同语言中实现中间层。

2、JDBC驱动程序的类型
客户端访问数据库服务器(DBMS)从本质上来说,是一个网络通信应用:TCP应用。具体为首先客户端发送SQL语句,然后DBMS返回SQL语句的结果。如SQL Server通过1433端口,Oralce通过1521端口来进行TCP通信。一般情况下,不需要直接与DBMS进行TCP通信,也不可能,因为厂家通常没有公开访问方法的细节。相反,DBMS厂家提供了一些函数库,程序代码通过调用这些函数对DBMS进行访问。这些函数处理与DBMS的TCP通信,在Windows/Unix平台函数的定义接口是相同的。这些函数(DB API)以动态链接库进行提供,它们是DBMS客户端的核心部分。如.dll,.so等。不同的数据库产品的客户端,DB API的定义和使用方法不一样。如SQL Server是Msdblib3.dll,Oracle是OCI.dll等。
当然层次越高,速度越慢,通用性越好。

JDBC包含三个组件:应用程序、驱动程序管理器和驱动程序。其中JDBC驱动程序的类型可以分为JDBC-ODBC桥加ODBC驱动程序、本地API、JDBC网络纯Java驱动程序、本地协议纯Java驱动程序。

1)JDBC-ODBC桥加ODBC驱动程序
利用ODBC驱动程序提供JDBC的访问,优点在于易于实现,缺点在于客户端需要安装ODBC驱动

2)本地API
直接调用客户机上的数据库驱动程序(如DLL文件等),缺点依然是客户端需要安装二进制驱动

3)JDBC网络纯Java驱动程序
本质上不算是新的一种形式,只是利用各种容器中间件间接访问数据库

4)本地协议纯Java驱动程序
直接利用TCP通信与数据库通信,无需任何API(其实是绕过API直接来作),如Oracle中的Oracle thin连接

3 JDBC开发流程
3、1 加载JDBC驱动
注意早期版本需要注册JDBC驱动程序,现在通过驱动程序类中的静态块都能自动完成注册,所以不再需要了。
注册方法为:
DriverManager.registerDriver(driver);
其中的driver就是要注册的新JDBC驱动程序

加载JDBC驱动的方法为:
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); (sun.jdbc.odbc.JdbcOdbcDriver类也可以实例化)
这是一个静态方法,用于指示JVM动态的查找、加载和链接指定类(如果没有加载),如果找不到这个类,则抛出ClassNotFoundException。

也可以使用加载:
sun.jdbc.odbc.JdbcOdbcDriver dr = new sun.jdbc.odbc.JdbcOdbcDriver();

3、2 连接数据库(得到Connection)
通过DriverManager.getConnection方法进行连接,如
Connection conn = DriverManager.getConnection(URL,login_name, login_password);
其中JDBC连接由数据库URL标识jdbc:<subprotocol>:<subname>来表示。

3、3 执行查询
Statement对象能够将SQL语句发送到DBMS,创建方法为:
Statement:执行SQL语句。conn.createStatement();
PreparedStatement:执行带参数SQL语句。conn.prepareStatement(“...”);
CallableStatement:执行存储过程。conn.prepareCall(“...”);

3、4 得到结果集
Statement接口的executeQuery:得到结果集ResultSet
Statement接口的executeUpdate:dml语句的执行结果
Statement接口的execute方法:底层方法,可得到多个结果集(如sql的compute by子句就能返回多个结果集)

3、5 处理结果集
利用ResultSet中的方法,如next(),getXXX(...);有些方法涉及到兼容性:first(),last()。

3、6 关闭Connection(关闭很重要)

一个简单的例子:
import java.sql.*;

public class exec
{
        public static void main(String [] args)
        {
                Connection con;
                Statement stm;
                ResultSet res;
        
        try
        {
                Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
                
                con = DriverManager.getConnection("jdbc:odbc:StuSQL" );
                
                stm=con.createStatement();              
                
                res=stm.executeQuery("select * from stu");
                
                while (res.next())
                {
                        System.out.println(res.getString(1));//begin at 1                      
                }
                        con.close();
        }
        catch(Exception ex)
        {}
        }
}
说明:
运行这个程序,需要实现在“控制面板”——“管理工具”——“数据源(ODBC)”中注册一个新的数据源,名称为“StuSQL”,具体的数据库类型和名称自己可以定义,但数据库中一定存在一个名称为“stu”的表

显示所有记录的所有字段
import java.sql.*;

public class exec
{
        public static void main(String [] args)
        {
                Connection con;
                Statement stm;
                ResultSet res;
                ResultSetMetaData rsmd;        
        try
        {
                Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
                
                con = DriverManager.getConnection("jdbc:odbc:StuSQL" );
                
                stm=con.createStatement();              
                
                res=stm.executeQuery("select * from stu");
                
                rsmd = res.getMetaData();
                
                while (res.next())
                {
                        for(int i=1;i<=rsmd.getColumnCount();i++)
                                System.out.print(res.getObject(i)+"\t");
                        System.out.println();
                }
                con.close();
        }
        catch(Exception ex)
        {}
        }
}

说明:
ResultSetMetaData和DatabaseMetaData类(通过Connection类的getMetaData方法获取)能够获取数据库的相关元数据信息。

下面的程序能够让用户输入学号,并显示的学生详细信息,如:
import java.sql.*;

public class exec
{
        public static void main(String [] args)
        {
                Connection con;
                Statement stm;
                ResultSet res;
                ResultSetMetaData rsmd;        
        try
        {
                Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
                
                con = DriverManager.getConnection("jdbc:odbc:StuSQL" );
                
                stm=con.createStatement();              
                
                String str=javax.swing.JOptionPane.showInputDialog("Please input the SID:");
                
                res=stm.executeQuery("select * from stu where number='"+str+"'");
                
                rsmd = res.getMetaData();
                
                while (res.next())
                {
                        for(int i=1;i<=rsmd.getColumnCount();i++)
                                System.out.print(res.getObject(i)+"\t");
                        System.out.println();
                }
                con.close();
                System.exit(0);
        }
        catch(Exception ex)
        {}              
        }
}

下面是一个swing版本的数据库演示程序:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.sql.*;

public class exec
{
        public static void main(String args[])
        {
                MyFrame m=new MyFrame("JDBC");
                Toolkit theKit = m.getToolkit();
                Dimension wndSize = theKit.getScreenSize();            
                m.setBounds(wndSize.width/4, wndSize.height/4, wndSize.width/2, wndSize.height/2);
                m.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                m.setVisible(true);
                m.pack();
        }
}

class MyFrame extends JFrame implements ActionListener
{
        Connection con;
        Statement stm;
        ResultSet res;  
        
        JLabel j1=new JLabel("学号");
        JLabel j2=new JLabel("姓名");
        JTextField jtf1=new JTextField(10);
        JTextField jtf2=new JTextField(10);
        JButton jb=new JButton("确定");
        
        JPanel jp1=new JPanel();
        JPanel jp2=new JPanel();
        
        public MyFrame(String title)
        {
                super(title);
                jp1.setLayout(new FlowLayout());
                jp1.add(j1);
                jp1.add(jtf1);
                
                jp1.setLayout(new FlowLayout());
                jp1.add(j2);
                jp1.add(jtf2);
                
                getContentPane().setLayout(new FlowLayout());
                getContentPane().add(jp1);
                getContentPane().add(jp2);
                getContentPane().add(jb);
                
                jb.addActionListener(this);
                
                try
                {
                        Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
                        con = DriverManager.getConnection("jdbc:odbc:StuSQL" );
                        stm=con.createStatement();
                }
                catch(Exception ex)
        {}
        }
        
        public void actionPerformed(ActionEvent e)
        {
                try
                {
                        res=stm.executeQuery("select name from stu where number='"+jtf1.getText()+"'");
                        res.next();
                        jtf2.setText(res.getString(1));
                con.close();
        }
        catch(Exception ex)
        {}    
        }
}

一般的统计记录个数程序:
import java.sql.*;

public class exec
{
        public static void main(String [] args)
        {
                Connection con;
                Statement stm;
                ResultSet res;
        
        try
        {
                Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
                
                con = DriverManager.getConnection("jdbc:odbc:StuSQL" );
                
                stm=con.createStatement();              
                
                res=stm.executeQuery("select * from stu");
                
                int count=0;
                while (res.next())
                {
                        count++;                
                }
                System.out.println(count);
                        con.close();
        }
        catch(Exception ex)
        {}
        }
}

更好的统计记录个数程序:
import java.sql.*;

public class exec
{
        public static void main(String [] args)
        {
                Connection con;
                Statement stm;
                ResultSet res;
        
        try
        {
                Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
                
                con = DriverManager.getConnection("jdbc:odbc:StuSQL" );
                
                stm=con.createStatement();              
                
                res=stm.executeQuery("select count(*) from stu");

                res.next();
                System.out.println(res.getInt(1));
                        con.close();
        }
        catch(Exception ex)
        {}
        }
}

4、执行DML语句
利用Statement对象的executeUpdate方法即可
import java.sql.*;

public class exec
{
        public static void main(String [] args)throws Exception
        {
                Connection con;
                Statement stm;
                ResultSet res;
        
        
                Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
                
                con = DriverManager.getConnection("jdbc:odbc:StuSQL" );
                
                stm=con.createStatement();              
                
                stm.executeUpdate("insert into stu values('000111','Ben',1,'1985-10-10',1.76)");

                con.close();
        
        }
}

5、调用存储过程(CallableStatement)
它是PreparedStatement子类,可以执行存储过程
如建立存储过程:
create proc stu_proc1
as select count(*) from stu

create proc stu_proc2
@pname char(6)
as select * from stu where number=@pname

create proc stu_proc3
@pname char(6),
@result char(8) output
as select @result=name from stu where number=@pname

一般的使用方法为:
import java.sql.*;

public class exec
{
public static void main(String [] args)
{
  Connection con;
  CallableStatement cstm;
  ResultSet res;
  ResultSetMetaData rsmd;  
       try
       {
        Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
        
        con = DriverManager.getConnection("jdbc:odbc:StuSQLServer" );
        
        cstm=con.prepareCall("{call stu_proc1}");
        
        res=cstm.executeQuery();
        
        rsmd = res.getMetaData();
        
        while (res.next())
        {
         for(int i=1;i<=rsmd.getColumnCount();i++)
          System.out.print(res.getObject(i)+"\t");
         System.out.println();
        }
        con.close();
       }
       catch(Exception ex)
       {}
      
}
}
说明:{call stu_proc1}为调用存储过程的语法,不是标准SQL的方法(所以不能用exec stu_proc1),而是JDBC的转义语法,它会自动将其转换成特定的DBMS格式

对于传入参数的使用方法为:
import java.sql.*;

public class exec
{
public static void main(String [] args)
{
  Connection con;
  CallableStatement cstm;
  ResultSet res;
  ResultSetMetaData rsmd;  
       try
       {
        Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
        
        con = DriverManager.getConnection("jdbc:odbc:StuSQLServer" );
        
        cstm=con.prepareCall("{call stu_proc2(?)}");
        cstm.setString(1,"000001");
        
        res=cstm.executeQuery();
        
        rsmd = res.getMetaData();
        
        while (res.next())
        {
         for(int i=1;i<=rsmd.getColumnCount();i++)
          System.out.print(res.getObject(i)+"\t");
         System.out.println();
        }
        con.close();
       }
       catch(Exception ex)
       {}
      
}
}
注意此程序要求的数据库字符型字段为char,而不能是nvarchar

对于传出参数的使用方法为:
SQLServer做法为
    String pcall="{call stu_proc3(?,?)}";
    CallableStatement cstmt=conn.prepareCall(pcall);
    cstmt.setString(1,"000001");
    cstmt.registerOutParameter(2,Types.VARCHAR);//重要,指定传出参数的类型
    cstmt.execute();    
    System.out.println(cstmt.getString(2));//重要,得到传出参数
如:
import java.sql.*;

public class exec
{
public static void main(String [] args)
{
  Connection con;
  CallableStatement cstm;
  ResultSet res;
  ResultSetMetaData rsmd;  
       try
       {
        Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
        
        con = DriverManager.getConnection("jdbc:odbc:StuSQLServer" );
        
        cstm=con.prepareCall("{call stu_proc3(?,?)}");
        cstm.setString(1,"000001");
        cstm.registerOutParameter(2,Types.VARCHAR);//重要,指定传出参数的类型
      cstm.execute();    
        
        System.out.println(cstm.getString(2));//重要,得到传出参数
        con.close();
       }
       catch(Exception ex)
       {}
      
}
}
注意此程序要求的数据库字符型字段为char,而不能是nvarchar

[此贴子已经被作者于2010-12-12 08:03:28编辑过]

 回到顶部