JDBC数据库操作.ppt
第11章 JDBC数据库操作11.1 Microsoft Access 11.1 Microsoft Access 数据数据库管理管理系系统 11.1.1 建立数据库 单击“开始”“所有程序”“Microsoft Office”“Microsoft Access”,在新建数据库界面选择“空Access数据库”,然后命名、保存新建的数据库,在这里我们命名的数据库是shop,保存在C:ch11中 图11.1 建立新Access的数据库图11.2 保存Access的数据库11.1.2 11.1.2 创建表建表 创建好数据库后,就可以在该数据库下建立若干个表。我们准备在shop数据库中创建名字为goods的表。在shop管理的“表”的界面上选择“使用设计器创建表”,然后单击界面上的“设计”菜单,将出现相应的建表界面,我们建立的表是goods,该表的字段(属性)为:number(文本)name(文本)madeTime(日期)price(数字,双精度)。其中,“number”字段为主键(在该字段上单击鼠标右建来设置字段是否是主建)在shop管理的“表”的界面上,用鼠标双击已创建的goods表可以为该表添加记录 图11.3 goods表及字段属性图11.4 向goods表添加记录11.2 JDBC 11.2 JDBC 为了使Java编写的程序不依赖于具体的数据库,Java提供了专门用于操作数据库的API,即JDBC 连接使用JDBC之应用程序所驻留的计算机应用程序JDBC数据库使用图11.5 使用JDBC操作数据库我们经常使用JDBC进行如下的操作:与一个数据库建立连接,向已连接的数据库发送SQL语句,处理SQL语句返回的结果。11.3 11.3 连接数据接数据库 11.3.1 连接方式的选择 和数据库建立连接的常用两种方式是:建立JDBCODBC桥接器和加载纯Java数据库驱动程序 为了便于教学,本章使用JDBCODBC桥接器方式和数据库建立连接 JDBCODBC桥接器的优点是:ODBC(Open DataBase Connectivity)是Microsoft引进的数据库连接技术,提供了数据库访问的通用平台,而且ODBC驱动程序被广泛的使用,建立这种桥接器后,使得JDBC有能力访问几乎所有类型的数据库。缺点是:使得应用程序依赖于ODBC,移植性较差,也就是说,应用程序所驻留的计算机必须提供ODBC(使用加载纯Java数据库驱动程序连接数据库的优点是不依赖平台)。图11.6 使用JDBCODBC桥接器方式ODBC数据源1(Oracle数据库)ODBC数据源2(Access数据库)ODBC数据源3(SQLServer数据库)连接使用JDBC之应用程序所驻留的计算机应用程序JDBC使用ODBC连接连接建 立桥 接器11.3.2 11.3.2 建立建立JDBC-ODBCJDBC-ODBC桥接器接器 JDBC使用java.lang包中的Class类建立JDBC-ODBC桥接器。Class类通过调用它的静态方法forName加载包中的JdbcOdbcDriver类建立JDBC-ODBC桥接器。建立桥接器时可能发生异常,必须捕获这个异常,建立桥接器的代码是:try);catch(ClassNotFoundException e)System.out.println(e);11.3.3 ODBC11.3.3 ODBC数据源数据源 1创建、修改或删除数据源选择“控制面板”“管理工具”“ODBC数据源”(某些window/xp系统,需选择“控制面板”“性能和维护”“管理工具”“ODBC数据源”)图11.7 添加、修改或删除数据源2为数据源选择驱动程序 在图11.7所示的界面上选择单击“添加”按钮,出现为新增的数据源选择驱动程序界面 图11.8 为新增的数据源选择驱动程序3数据源名称及对应数据库的所在位置 在图11.8界面单击完成按钮将出现设置数据源具体项目的对话框 图11.9 设置数据源的名字和对应的数据库11.3.4 11.3.4 建立建立连接接 编写连接数据库代码不会出现数据库的名称,只能出现数据源的名字。首先使用java.sql包中的Connection类声明一个对象,然后再使用类DriverManager调用它的静态方法getConnection创建这个连接对象:Connection con=DriverManager.getConnection(jdbc:odbc:数据源名字,login name,password);假如没有为数据源设置login name 和password,那么连接形式是:Connection con=DriverManager.getConnection(jdbc:odbc:数据源名字,);为了能和数据源myData交换数据,建立连接时应捕获SQLException异常:try Connection con=DriverManager.getConnection(jdbc:odbc:myData,);catch(SQLException e)11.4 11.4 查询操作操作 1向数据库发送SQL查询语句首先使用Statement声明一个SQL语句对象,然后让已创建的连接对象con调用方法createStatment()创建这个SQL语句对象,代码如下:try Statement sql=con.createStatement();catch(SQLException e)2处理查询结果有了SQL语句对象后,这个对象就可以调用相应的方法实现对数据库中表的查询和修改,并将查询结果存放在一个ResultSet类声明的对象中。也就是说SQL查询语句对数据库的查询操作将返回一个ResultSet对象,ResultSet对象是以统一形式的列组织的数据行组成。ResultSet对象一次只能看到一个数据行,使用next()方法走到下一数据行,获得一行数据后,ResultSet对象可以使用getXxx方法获得字段值,将位置索引(第一列使用1,第二列使用2等等)或列名传递给getXxx方法的参数即可 11.4.1 11.4.1 顺序序查询 怎样知道一个表中有哪些字段呢?通过使用JDBC提供的API,可以在查询之前知道表中的字段的个数和名字,这有助于编写可复用的查询代码 当创建好连接对象con之后,那么该连接对象调用getMetaData()方法可以返回一个DatabaseMetaData对象,例如:DatabaseMetaData metadata=con.getMetaData();Metadata对象再调用getColumns可以将表的字段信息以行列的形式存储在一个ResultSet对象中 例如:ResultSet tableMessage=metadata.getColumns(null,null,goods,null);如果goods表有n个字段,tableMessage就刚好有n行、每行4列。每行分别含有和相应字段有关的信息,信息的次序为:“数据库名”、“数据库扩展名”、“表名”,“字段名”。tableMessage对象调用next方法使游标向下移动一行(游标的初始位置在第1行之前),然后tableMessage调用getXXX方法可以查看该行中列的信息 11.4.2 11.4.2 控制游控制游标 有时候需要在结果集中前后移动、显示结果集中某条记录或随机显示若干条记录等。这时,必须要返回一个可滚动的结果集。为了得到一个可滚动的结果集,需使用下述方法获得一个Statement对象:Statement stmt=con.createStatement(int type,int concurrency);然后,根据参数的type、concurrency的取值情况,stmt返回相应类型的结果集:ResultSet re=stmt.executeQuery(SQL语句);type的取值决定滚动方式,取值可以是:ResultSet.TYPE_FORWORD_ONLY:结果集的游标只能向下滚动。ResultSet.TYPE_SCROLL_INSENSITIVE:结果集的游标可以上下移动,当数据库变化时,当前结果集不变。ResultSet.TYPE_SCROLL_SENSITIVE:返回可滚动的结果集,当数据库变化时,当前结果集同步改变。Concurrency 取值决定是否可以用结果集更新数据库,Concurrency取值:ResultSet.CONCUR_READ_ONLY:不能用结果集更新数据库中的表。ResultSet.CONCUR_UPDATABLE:能用结果集更新数据库中的表。滚动查询经常用到ResultSet的下述方法:public boolean previous():将游标向上移动,该方法返回boolean型数据,当移到结果集第一行之前时返回false.public void beforeFirst:将游标移动到结果集的初始位置,即在第一行之前。public void afterLast():将游标移到结果集最后一行之后。public void first():将游标移到结果集的第一行。public void last():将游标移到结果集的最后一行。public boolean isAfterLast():判断游标是否在最后一行之后。public boolean isBeforeFirst():判断游标是否在第一行之前public boolean ifFirst():判断游标是否指向结果集的第一行。public boolean isLast():判断游标是否指向结果集的最后一行。public int getRow():得到当前游标所指行的行号,行号从1开始,如果结果集没有行,返回0public boolean absolute(int row):将游标移到参数row指定的行号。11.4.3 11.4.3 条件条件查询 见例11-411.4.4 11.4.4 排序排序查询 可以在SQL语句中使用ORDER BY子语句对记录排序,例如,按price排序查询的SQL语句:SELECT*FROM goods ORDER BY price 11.4.5 11.4.5 模糊模糊查询 可以用SQL语句操作符LIKE进行模式般配,使用“%”代替零个或多个字符,用一个下划线“_”代替一个字符,用abc代替a、b、c中的任何一个。比如,下述语句查询商品名称中含有“电”或“箱”的记录:rs=sql.executeQuery(SELECT*FROM goods WHERE name LIKE 电箱%);11.5 11.5 更新、添加与更新、添加与删除操作除操作 Statement对象调用方法:public int executeUpdate(String sqlStatement);通过参数sqlStatement指定的方式实现对数据库表中记录的更新、添加和删除操作。更新、添加和删除记录的SQL语法分别是:UPDATE SET =新值 WHERE INSERT INTO 表(字段列表)VALUES(对应的具体的记录)或INSERT INTO 表(VALUES(对应的具体的记录)DELETE FROM WHERE 11.6 11.6 使用使用预处理理语句句 Java提供了更高效率的数据库操作机制,就是PreparedStatement对象,该对象被习惯地称作预处理语句对象。11.6.1 11.6.1 预处理理语句句优点点 如果应用程序能针对连接的数据库,事先就将SQL语句解释为数据库地层的内部命令,然后直接让数据库去执行这个命令,显然不仅减轻了数据库的负担,而且也提高了访问数据库的速度。对于JDBC,如果使用Connection和某个数据库建立了连接对象con,那么con就可以调用prepareStatement(String sql)方法对参数sql指定的SQL语句进行预编译处理,生成该数据库地层的内部命令,并将该命令封装在PreparedStatement对象中,那么该对象调用下列方法都可以使得该地层内部命令被数据库执行,ResultSet executeQuery()boolean execute()int executeUpdate()只要编译好了PreparedStatement对象,那么该对象可以随时地执行上述方法,显然提高了访问数据库的速度。11.6.2 11.6.2 使用使用统配符配符 在对SQL进行预处理时可以使用统配符“?”来代替字段的值,只要在预处理语句执行之前再设置统配符所表示的具体值即可。例如:sql=con.prepareStatement(SELECT*FROM goods WHERE salary?);那么在sql对象执行之前,必须调用相应的方法设置统配符“?”代表的具体值,比如:sql.setFloat(1,76.98);指定上述预处理SQL语句中统配符“?”代表的值是76.389 通配符按着它们在预处理SQL语句中从左到右依次出现的顺序分别被称做第1个、第2个 第m个统配符。比如,下列方法:void setFloat(intparameterIndex,intx)用来设置通配符的值,其中参数parameterIndex用来表示SQL语句中从左到右的第parameterIndex个统配符号,x是该统配符所代表的具体值 尽管sql=con.prepareStatement(SELECT*FROM goods WHERE price?);sql.setFloat(1,30.98);的功能等同于sql=con.prepareStatement(SELECT*FROM goods WHERE price 3000);之后立刻关闭连接:con.close();那么输出结果集中的数据的代码:while(rs.next()就无法执行。在前面的诸多例子,必须在操作结果集ResultSet的语句之后才执行关闭连接:con.close();包提供了CachedRowSetImpl类,该类实现了CachedRowSet接口。CachedRowSetImpl对象可以保存ResultSet对象中的数据,而且CachedRowSetImpl对象不依赖Connnection对象,这意味着一旦把ResultSet对象中的数据保存到CachedRowSetImpl对象中后,就可以关闭和数据库的连接。CachedRowSetImpl继承了ResultSet的所有方法,因此可以像操作ResultSet对象一样来操作CachedRowSetImpl对象。将ResultSet对象rs中的数据保存到CachedRowSetImpl对象rowSet中的代码如下:rowSet.populate(rs);