620 likes | 810 Views
数据库访问. 主要内容 数据库管理系统 Java 与 数据库编程 数据库 的连接 数据 表的查询 查询中的异常处理 数据的添加和修改 C/S 方式数据库访问. 数据库管理系统. 数据库管理系统 ( DataBase Management System,DBMS): 数据库管理系统是位于数据库使用者与数据库操作系统之间的一层数据管理软件,它是由系统运行控制程序 、 语言翻译程序和一组公用程序所组成。. 数据库应用程序1. 数据库管理系统( DBMS). 数据库. 数据库应用程序2.
E N D
数据库访问 • 主要内容 • 数据库管理系统 • Java与数据库编程 • 数据库的连接 • 数据表的查询 • 查询中的异常处理 • 数据的添加和修改 • C/S方式数据库访问
数据库管理系统 • 数据库管理系统 (DataBase Management System,DBMS): • 数据库管理系统是位于数据库使用者与数据库操作系统之间的一层数据管理软件,它是由系统运行控制程序、语言翻译程序和一组公用程序所组成。 数据库应用程序1 数据库管理系统(DBMS) 数据库 数据库应用程序2 数据库管理员(DBA)
数据库管理系统功能 • 数据定义功能 (Data Definition Language,DDL) • 定义数据,建立数据的完整性约束条件等。 • 数据操纵功能 (Data Manipulation Language,DML) • 实现对数据库的数据存取、更新管理等基本操作。 • 数据库的控制功能 • 是DBMS的核心部分,包括并发控制、数据的安全检测、完整性约束条件和权限控制等。 • 数据库的维护功能 • 包括各种类型的故障恢复、数据库的转储、数据库的重组和性能监视、分析功能等。 • 数据字典功能 (Data Dictionary,DD)
数据库访问模式 数据库访问的两层结构 DBMS JDBC接口 Java应用程序 数据库 客户机 数据库服务器 • 三层结构网络数据库系统 SQL命令 通信协议 Applet客户界面 Servlet数据库服务程序 数据库 客户机 Web服务器 数据库服务器
关系型数据库的基本概念 • 库(database): 相关数据表的集合 • 表(table):由若干行和若干列组成的数据组(即二维矩阵) • 记录(recode):存放在表中的一行称为一个“记录’’ • 字段(field):表中的域,称为 ‘‘字段’’ • 键(key): • 用于表中快速检索和分类。分为:主键或外键 • 键在表中可指定为某个(或多个)字段,键值在表中 是有序的。如果作为主键,其值在表中是唯一的。 列(column) 行(row)
SQL语言 • SQL( Structured Query Language) • 结构查询语言 • 是专门为数据库而建立的操作命令集,是一种功能齐全的数据库语言。 • SQL语言提供多任务的命令:包括建立、修改和删除数据库对象,在表中插入、修改和删除记录,查询、检索和筛选数据,控制对数据和数据对象的存取等等。 • 关系型数据库管理系统都支持SQL语言
SQL语言的使用方法 • SQL语言有三种使用方式 • 交互式:终端操作员在控制台直接用命令操纵数据库。 • 嵌入式:即SQL语句嵌入到某种高级程序语言(如:C、Pascal、Java等),在应用程序中调用它操纵数据库。 • 过程式:用SQL语言编写独立的并存储在数据库中的程序,称之为“存储过程” ,用该程序名称像调用方法一样使用。
数据定义语句 • 创建数据库: create database 数据库名 [其他参数] 如:create database student; • 创建表: create table 表名( 列名1 类型, 列名2 类型, 。。。 列名n 类型 );
数据查询语句 • 语句格式: select [ unique | distinct ] 列名1 [,列名2 ,…,列名n ] from 表名 [ where <条件> ] [ group by 列名] [ having 条件 ] [ order by 分类说明 ] • *可代表所有列名。 如:select * from chengjibiao
数据修改语句 • 插入记录 insert into 表名(列名1,列名2,。。。列名n) values(数据1,数据2,。。。数据n) • 数据修改 update 表名 set 列名1=数据表达式1 [ , … , 列名n=数据表达式n] [ where 条件;] • 删除记录 delete from 表名 [ where 条件]
应用程序与数据库的通讯连接 数据库应用程序 API函数调用 数据 ODBC驱动管理器 (JDBC:ODBC) ODBC驱动程序调用 数据 数据库驱动程序 数据库接口调用 数据 数据库通信协议 SQL命令 数据 数据库操作系统
Java与数据库连接接口方式 • JDBC(Java DataBase Connectivity) • Java提供的数据库连接API工具 • 在java程序中通过JDBC连接方式,嵌入使用SQL语言,可以访问网上的任意关系型数据库 • JDBC独立于平台和数据库 • JDBC能完成的三个任务 • 建立与数据库的连接; • 向数据库系统发送SQL语句; • 处理数据库查询返回的结果。
Java与数据库操作编程 编程要点:嵌入式SQL的操作过程 • 引入包 java.sql • 建立数据库连接方式 • JDBC(Java DataBase Connectivity) • JDBC-ODBC桥接器 • 程序连接到数据库 • Connection类 • 向数据库发送SQL语句 • 处理查询返回结果
程序中建立连接方式 • 建立JDBC-ODBC桥接器 • 调用类方法 Class.forName(String s) 例如: try{ Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”); } catch ( ClassNotFoundException e) { } • 注意:建立桥接器时可能发生异常,因此必须捕获这个异常。 连接驱动程序
建立连接数据库对象 • 声明Connection对象 • 创建连接数据库源对象的方法 • 使用类DriverManager的类方法getConnection创建这个连接对象: 如: try { Connection con= DriverManager. getConnection( “jdbc:odbc:redsun”, “snow”, “ookk”); }catch(SQLException e) { } 操作密码 数据源 操作员
创建SQL语句对象 • 先用Statement声明一个SQL语句对象, • 然后通过创建的连接数据库的对象con,调用createStatement()方法创建这个SQL语句对象。 如: Statement sql; try{ sql=con.createStatement(); } catch(SQLException e) { }
执行SQL查询与返回结果 • 用sql对象调用相应的方法实现对数据库的查询和修改。 1。查询结果放入一个ResultSet对象中。 如: ResultSet rs = sql.executeQuery (“SELECT * FROM chengjibiao”); • ResultSet对象是一个管式数据集,即它是由统一形式的列组成的数据行。 2。ResultSet对象一次只能获得一个数据行,用 next()方法可取下一数据行(记录)。 3。ResuItSet对象可以用列名称或位置索引(第一列使用1,笫二列使用2,等等) , 调用 getXXX() 方法获得记录的字段值。
ResultSet对象的若干方法 • next() 返回 boolean • getByte(intcolumnIndex) 返回 byte • getDate(int columnIndex) 返回 Date • getDouble(int columnIndex) • getFloat(int columnIndex) • getInt(int columnIndex) • getLong(int columnIndex) • getString(int columnIndex) 。。。。。 • getLong(String columnName) • getString(StringcolumnName) 位置索引 字段名称
应用举例1 一个数据库查询的例子 • 注意:运行前先建立数据源 • 建立数据库 • 建立ODBC数据源 Java程序查询结果
import java.sql.*; public class Example23_1 { public static void main(String args[]) { Connection con; Statement sql; ResultSet rs; try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); } catch(ClassNotFoundException e) { System.out.println(""+e); } try { con=DriverManager.getConnection("jdbc:odbc:redsun","snow","ookk"); sql=con.createStatement(); rs=sql.executeQuery("SELECT * FROM chengjibiao"); while(rs.next()) { String number=rs.getString(1); String name=rs.getString(2); Date date=rs.getDate(3); int math=rs.getInt("数学"); int physics=rs.getInt(“物理”); int english=rs.getInt("英语"); 例子1
例子1(续) System.out.print("学号:"+number); System.out.print(" 姓名:"+name); System.out.print(" 出生:"+date); System.out.print(" 数学:"+math); System.out.print(" 物理:"+physics); System.out.println(" 英语:"+english); } con.close(); } catch(SQLException e1) {} } }
配置数据源 • 在ODBC管理器中配置student.mdb数据库 步骤如下: 1.在Windows操作系统的控制面板中启动ODBC管理器程序 2.在ODBC管理器中单击“添加”按钮,出现创建新数据源界面 3.创建新数据源中选择Access(*.mdb)数据源。 单击“完成”按钮,出现安装Access数据库界面 4 .单击数据库区域的“选择”按钮,选择Access数据库(student.mdb),在数据源名处为该数据源命名。 当需要为该数据源授权访问级别时, 单击“高级’’按钮 5 . 设置登录数据库名和密码后,单击界面中“确定”按钮,则完成Access数据库在ODBC 管理器中配置。
应用举例2 • 例子2 • 查询“英语” 字段值大于80的记录,只显示“姓名”字段和“英语”字段。
import java.sql.*; public class Example23_2 { public static void main(String args[]) { Connection con; Statement sql; ResultSet rs; try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); } catch(ClassNotFoundException e) { System.out.println(""+e); } try { con=DriverManager.getConnection("jdbc:odbc:redsun","snow","ookk"); sql=con.createStatement(); rs=sql.executeQuery( "SELECT 姓名,英语 FROM chengjibiao WHERE 英语 >= 80 "); while(rs.next()) { String name=rs.getString(1); int english=rs.getInt(2); System.out.print("姓名:"+name); System.out.println("英语:"+english); } 。。。 。。。 例子2
应用举例3 • 例子3 • 一个“英汉小词典’’程序实例,词典的内容放在一个Access数据库的表中。
import java.awt.*; import java.net.*; import java.sql.*; import java.awt.event.*; class DataWindow extends Frame implements ActionListener { TextField englishtext; TextArea chinesetext; Button button; DataWindow() { super("英汉小字典"); setBackground(Color.cyan); setBounds(150,150,300,120); setVisible(true); englishtext=new TextField(16); chinesetext=new TextArea(5,10); button=new Button("确定"); Panel p1=new Panel(),p2=new Panel(); p1.add(new Label("输入要查询的单词:")); p1.add(englishtext); p2.add(button); add(p1,"North"); add(p2,"South"); add(chinesetext,"Center"); chinesetext.setBackground(Color.pink); button.addActionListener(this); addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {setVisible(false); System.exit(0);} }); } 例子23-3
public void actionPerformed(ActionEvent e) { if(e.getSource()==button) { chinesetext.setText("查询结果"); try { Liststudent(); } catch( SQLException ee ){ } } } public void Liststudent() throws SQLException { String cname, ename; try{ Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); } catch(ClassNotFoundException e){} Connection Ex1Con= DriverManager.getConnection("jdbc:odbc:test","gxy","ookk"); Statement Ex1Stmt=Ex1Con.createStatement(); ResultSet rs=Ex1Stmt.executeQuery("SELECT * FROM 表1 "); while(rs.next()) { ename=rs.getString(“单词”); cname=rs.getString("解释"); 例子23-3(续) 抛出异常
例子23-3(续2) if (ename.equals(englishtext.getText())) { chinesetext.append('\n'+cname);break;} } Ex1Con.close(); if(chinesetext.getText().trim().equals("查询结果")) {chinesetext.append('\n'+"没有该单词");} } } public class Example23_3 {public static void main(String args[]) { DataWindow window=new DataWindow(); window.pack(); } }
可滚动结果集 • 可滚动结果集 • 在结果集中前后移动、或显示结果集指定的记录 • 获得一个Statement可滚动结果的对象 Statement stmt=con. createStatement(int type,int concurrency); • 然后,根据参数的type、concurrency的取值情况,stmt返回相应类型的结果集. ResultSet re=stmt.executeQuery( SQL语句 );
可滚动集type、 concurrency的取值 • type的取值决定滚动方式: ResultSet.TYPE_FORWORD_ONLY 结果集的游标只能向下滚动。 ResultSet.TYPE_SCROLL_INSENSITIVE 游标可上下移动,当数据库变化时,当前结果集不变。 ResultSet.TYPE_SCROLL_SENSITIVE 游标可上下移动, 当数据库变化时,当前结果集同步改变。 • concurrency取值决定是否可以用结果集更新数据库 ResultSet.CONCUR_READ_ONLY 不能用结果集更新数据库中的表。 ResultSet.CONCUR_UPDATETABLE 能用结果集更新数据库中的表。
可滚动集使用的方法 • boolean previous()将游标向上移动,该方法返回boolean型数据, 当移到结果集第一行之前时返回false。 • void beforeFirst()将游标移动到结果集的初始位置,即第一行前。 • void afterLast()将游标移到结果集最后一行之后。 • void first()将游标移到结果集的第一行。 • void last()将游标移到结果集的最后一行。 • boolean isAfterLast()判断游标是否在最后一行之后。 • boolean isBeforeFirst()判断游标是否在第一行之前。 • boolean ifFirst()判断游标是否指向结果集的第一行。 • boolean isLast()判断游标是否指向结果集的最后一行。 • int getRow()获取当前游标所指行的行号, 行号从1开始,如果结果集没有行,返回0。 • boolean absolute(int row)将游标移到参数row指定的行号。
可滚动集应用举例 • 例子 • 把成绩表中英语80分以上的学生找出来,并按照查询结果的记录集,让先找到的记录后显示。也可指定某一行结果显示。
import java.sql.*; public class Example23_4 { public static void main(String args[]) { Connection con; Statement sql; ResultSet rs; try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); } catch( ClassNotFoundException e ) { System.out.println(""+e); } try { con=DriverManager.getConnection ("jdbc:odbc:redsun", "snow", "ookk" ) ; sql=con.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY) ; //返回可滚动的结果集 rs=sql.executeQuery( "SELECT 姓名,英语 FROM chengjibiao WHERE 英语>=80" ) ; 例子23-4
例子23-4(续) rs.last();//将游标移动到最后一行 int number=rs.getRow( ) ; //获取最后一行的行号 System.out.println( "英语>=80的共有"+number+"条记录" ) ; //为了逆序输出记录,需将游标移动到最后一行之后 rs.afterLast() ; while(rs.previous()) { String name=rs.getString(1) ; int english=rs.getInt("英语") ; System.out.print("行号: "+rs.getRow()) ; System.out.print("\t姓名: "+name) ; System.out.println("\t英语: "+english) ; }
例子23-4(续2) System.out.println("单独输出第3条记录: ") ; rs.absolute(3) ; String name=rs.getString(1) ; int english=rs.getInt("英语") ; System.out.print("姓名: "+name) ; System.out.println("\t英语: "+english) ; con.close() ; } catch(SQLException e1) { System.out.println("*** ERR "+e1); } } }
排序查询和模糊查询 • 排序查询 executeQuery(“SELECT * FROM student ORDER BY 数学”); • 模糊查询 executeQuery (“SELECT * FROM student WHERE 姓名 LIKE ‘王%’ ”); DESC 表示 降序 ASC 表示 升序 % 表示 0个或多个字符 _ 表示 1个字符
数据库表中记录的更新 • 数据的修改 executeUpdate( “UPDATE 表1 SET 解释=‘小汽车’ WHERE 单词=‘car’ ”); • 记录的添加 executeUpdate( “INSERT INTO 表1 VALUES(‘girl’, ‘女孩’) ”);
数据库表中记录更新举例 查询语句 stmt. executeQuery()方法 修改语句 stmt. executeUpdate()方法
if(e.getSource()==更新按钮) { try{ 更新() ; } catch(SQLException ee) {}} 例子23-7 代码片段: 数据库记录更新方法 …… public void 更新()throws SQLException { String s1=“’”+更新英文单词_文本条.getText().trim()+”’”, s2=“’”+更新汉语解释_文本条.getText().trim()+”’”; String temp= “UPDATE 表1 SET 解释 = ” + s2 + “ WHERE 单词 = ” + s1; con=DriverManager.getConnection( “jdbc:odbc:moon”, “ gxy”, “ ookk” ); stmt=con.createStatement(); stmt.executeUpdate( temp ); con.close(); } ……
数据库表中记录的删除 executeUpdate( “DELETE FROM 表1 WHERE 单词=‘car’ ”); …… public void 删除()throws SQLException { String s3=“’”+删除英文单词_文本条.getText().trim()+”’”, String temp=“DELETE FROM 表1 WHERE 单词 = ” + s3; con=DriverManager.getConnection( “jdbc:odbc:moon”, “ gxy”, “ ookk” ); stmt=con.createStatement(); stmt.executeUpdate( temp ); con.close(); } ……
预处理语句 • 预处理 • 事先将SQL语句解释为数据库底层的内部命令,然后直接让数据库去执行这个命令。 • 调用 prepareStatement( String sqlcmd ) 进行编译预处理,生成内部命令。 • 对象调用 ResultSet executeQuery() boolean execute() int executeUpdate() 方法,操作执行数据库
import java.sql.*;public class DatabasePrepare{ public static void main(String args[]) { Connection con; PreparedStatement sql; ResultSet rs; try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); } catch(ClassNotFoundException e) { System.out.println(""+e); } try { con=DriverManager.getConnection("jdbc:odbc:sun","gxy","123");sql=con.prepareStatement("SELECT * FROM chengjibiao"); rs=sql.executeQuery(); while(rs.next()) { String number=rs.getString(1); String name=rs.getString(2); System.out.print("学号:"+number); System.out.println(" 姓名:"+name); } con.close(); } catch(SQLException e) { System.out.println(e); } } }
使用通配符 • 过程 • 进行预处理时可以使用通配符‘?’来代替字段值, • 在执行时给出具体数值。 • 举例 sql3=con.prepareStatement( “SELECT * FORM chengjibiao WHERE math < ?” ); 执行时: sql3.setInt( 1, 89); rs=sql3.executeQuery(); 在第一个‘?’处赋数值89
使用通配符方法 • 常用方法 setDate(int parameterIndex, Date x) setDouble(int parameterIndex, double x) setFloat(int parameterIndex, float x) setInt(int parameterIndex, int x) setLong(int parameterIndex, long x) setString(int parameterIndex, String x)
通配符举例 … … sqlTwo=con.prepareStatement("INSERT INTO chengjibiao VALUES (?, ?, ?, ?, ?)"); sqlTwo.setString(1, "2003888"); sqlTwo.setString(2, "李向阳");sqlTwo.setString(3, "1919-05-04"); sqlTwo.setInt(4, 99); sqlTwo.setInt(5, 88); sqlTwo.executeUpdate();… …
C/S方式数据库访问 • 利用网络套接字技术实现应用程序中对服务器数据库的访问。 • 客户端的应用程序只是利用套接字连接向服务器发送一个查询的条件。 • 服务器端负责对数据库进行查询,然后服务器将查询的结果利用建立的套接字返回给客户端。 • 注意:如果用这种方式访问数据库,那么客户端不需要任何数据库驱动程序 • 例子23-8
import java.net.*; import java.io.*; import java.awt.*; import java.awt.event.*; import java.applet.*; public class Database_client extends Applet implements Runnable,ActionListener{ Button 查询;TextField 英文单词_文本框, 汉语解释_文本框; Socket socket = null; DataInputStream in = null; DataOutputStream out = null; Thread thread; public void init(){ 查询 = new Button("查询"); 英文单词_文本框 = new TextField(10); 汉语解释_文本框 = new TextField(10); add(new Label("输入要查询的英文单词")); add(英文单词_文本框); add(new Label("汉语解释:")); add(汉语解释_文本框); add(查询); 查询.addActionListener(this); } 例子23-8 Database_Client端
public void start(){ try{ socket = new Socket(this.getCodeBase().getHost(),4331); in = new DataInputStream(socket.getInputStream()); out = new DataOutputStream(socket.getOutputStream()); } catch(IOException e){} if (thread == null){ thread = new Thread(this); thread.setPriority(Thread.MIN_PRIORITY); thread.start(); } } public void stop(){ try{ out.writeUTF("客户离开"); } catch(IOException e1){} } Database_Client端(续)
Database_Client端(续2) public void destory(){ try{ out.writeUTF("客户离开"); }catch(IOException e1){} } public void run(){ String s = null; while(true){ try{ s=in.readUTF(); } catch(IOException e){ 汉语解释_文本框.setText("与服务器已断开"); break; } 汉语解释_文本框.setText(s); } }