第23课JDBC编程(下_第1页
第23课JDBC编程(下_第2页
第23课JDBC编程(下_第3页
第23课JDBC编程(下_第4页
第23课JDBC编程(下_第5页
已阅读5页,还剩71页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、JDBC编程(下)内容概要对数据库进行SQL语句进行基本操作预编译语句使用事务事务的级别控制 使用存储过程 操作元数据 可滚动的和可更新的结果集 批处理更新 字符大对象CLOB二进制大对象BLOBJDK5新特性对数据库进行SQL语句进行基本操作创建表: 使用JDBC创建数据库表的步骤为: 1,Creating JDBC Statements 2,Executing Statements 3,Entering Data into a Table请看下列: import java.sql.Connection;import java.sql.Statement;public class Creat

2、eTable public CreateTable() super();public static void main(String args) Connection con=null;try/通过连接池来获得一个连接con=DBCon.getConnectionFromPooledDataSource(jdbcPool/mydatasource);/创建语句对象Statement st=con.createStatement();/创建表的SQL语句String sql=create table student(id int,name char(30),age int);/执行完SQL语句的

3、结果boolean b=st.execute(sql);/true if the first result is a ResultSet object; /false if it is an update count or/there are no results if(b=false)System.out.println(create success);elseSystem.out.println(create fail);catch(Exception e)e.printStackTrace();finallytryif(con!=null)/用完连接后,要关闭释放con.close();

4、catch(Exception e)e.printStackTrace();下面给表插入值:import java.sql.Connection;import java.sql.Statement;public class InsertValues public InsertValues() super();/ TODO Auto-generated constructor stub/* * param args */public static void main(String args) Connection con=null;try/通过连接池来获得一个连接con=DBCon.getCon

5、nectionFromPooledDataSource(jdbcPool/mydatasource);/创建语句对象Statement st=con.createStatement();/给student表插入值的SQL语句String sql=insert into student values(1,andy,47)+insert into student values(2,jacky,53)+insert into student values(3,周润发,51)+insert into student values(4,谢贤,60);/执行完SQL语句的结果boolean b=st.ex

6、ecute(sql);/true if the first result is a ResultSet object; /false if it is an update count or/there are no results if(b=false)System.out.println(insert success);elseSystem.out.println(create fail);catch(Exception e)e.printStackTrace();finallytryif(con!=null)/用完连接后,要关闭释放con.close();catch(Exception e

7、)e.printStackTrace();查询数据库里的数据 Statement对象的execQuery()方法一般用于执行一个select语句,它只返回一个结果集,要想把查询结果最后显示给用户,必须对ResultSet对象进行处理。ResultSet对象包括一个由查询语句返回的一个表,这个表中包含所有的查询结果。对ResultSet对象的处理必须逐行进行,而对每一行中的各个列,可以按任何顺利进行处理。ResultSet对象维持一个指向当前行的指针(类似于Iterator的用法)。最初,这个指针指向第一行之前。ResultSet的next()方法使这个指针移向下一行。因此,第一次使用next(

8、)方法将指针指向结果集的第一行,这是可以对第一行的数据进行处理。处理完毕后,使用next()方法,将指针移向下一行,继续处理第二行数据。next()方法的返回值是一个boolean值,若为true,则说明指针成功地移向下一行,可以对该行进行处理。若返回值是false,则说明没有下一行,即结果集已经处理完毕。在对每一行进行处理时,可以对各个列按任意顺序进行处理。不过,按从左至右的顺序对各列进行处理可以获得较高的执行效率。ResultSet接口的getXXX()方法可以从某列中获得结果,XXX表示JDBC的数据类型。请看下例:import java.sql.Connection;import ja

9、va.sql.ResultSet;import java.sql.ResultSetMetaData;import java.sql.Statement;public class ResultSetTest public ResultSetTest() super();/ TODO Auto-generated constructor stub/* * param args */public static void main(String args) Connection con=null;try/通过连接池来获得一个连接con=DBCon.getConnectionFromPooledDat

10、aSource(jdbcPool/mydatasource);/创建语句对象Statement st=con.createStatement();/定义一个查询的SQL语句String query=select id,name from student;/获得一个结果集ResultSet rs=st.executeQuery(query);/获得结果集的元数据(表及的信息)ResultSetMetaData rsmt=rs.getMetaData();/得到有几列,保存在num变量里int num=rsmt.getColumnCount();String columns=new Stringn

11、um;/列的序号是从1开始的for(int i=0;inum;i+)columnsi=rsmt.getColumnName(i+1);/先输出列名for(int i=0;inum;i+)System.out.print(columnsi+ );/输出列名之后换行System.out.println();/取出结果while(rs.next()/输出每一行的值for(int i=1;i0)System.out.println(update success);elseSystem.out.println(update fail);catch(Exception e)e.printStackTrac

12、e();finallytryif(con!=null)/用完连接后,要关闭释放con.close();catch(Exception e)e.printStackTrace();预编译语句(PreparedStatement)Statement对象在每次执行SQL语句时都将该语句传给数据库,在多次执行同一语句时,这样做效率较低。这时可以使用PreparedStatement对象.如果数据库支持预编译,它可以将SQL语句传给数据库作预编译,以后每次执行这个SQL语句时,速度就可以提高很多。如果数据库不支持预编译,则在语句执行时,才将其传给数据库。这对用户来说是透明的。PreparedStatem

13、ent对象的SQL语句还可以接受参数。在语句中指出需要接受哪些参数,然后进行预编译。在每一次执行时,可以给SQL语句传输不同的参数,这样就大大提高了灵活性。PreparedStatement接口是Statement接口派生的子接口,因此它可以使用Statement接口中的方法。请看下列代码:import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.sql.Statement;public

14、class PrepareStatementTest public PrepareStatementTest() super();/ TODO Auto-generated constructor stub/* * param args */public static void main(String args) Connection con=null;try/通过连接池来获得一个连接con=DBCon.getConnectionFromPooledDataSource(jdbcPool/mydatasource);/创建修改表的PrepareStatement SQL语句String sql

15、=update student set name=?+ where id=?;/创建预编译语句对象PreparedStatement st=con.prepareStatement(sql);String names=new String梁朝伟,贝壳汗母,小罗,霍元甲;for(int i=0;inames.length;i+)st.setString(1,namesi);st.setInt(2,i+1);st.executeUpdate();st.close();/打印执行完SQL语句的结果Statement stq=con.createStatement();/定义一个查询的SQL语句Str

16、ing query=select id,name from student;/获得一个结果集ResultSet rs=stq.executeQuery(query);/获得结果集的元数据(表及的信息)ResultSetMetaData rsmt=rs.getMetaData();/得到有几列,保存在num变量里int num=rsmt.getColumnCount();String columns=new Stringnum;/列的序号是从1开始的for(int i=0;inum;i+)columnsi=rsmt.getColumnName(i+1);/先输出列名for(int i=0;inu

17、m;i+)System.out.print(columnsi+ );/输出列名之后换行System.out.println();/取出结果while(rs.next()/输出每一行的值for(int i=1;i=num;i+)String temp=rs.getString(i);System.out.print(temp+ );/输完后换行System.out.println();catch(Exception e)e.printStackTrace();finallytryif(con!=null)/用完连接后,要关闭释放con.close();catch(Exception e)e.pr

18、intStackTrace();使用事务下面介绍如何把一系列语句组织成一个事务?如果事务中所有命令都能正确执行,就可以提交这个事务;否则,如果事务中有一个命令出现错误,回滚这个事务,并返回到提交之前的状态,好象什么也没有发生。把命令组合成事物的主要原因是保证数据库的完整性。对于一个事务而言,要么事务中语句全部得到正确执行,事务就可被提交了,要么它中间出现错误。后一种情况,可以调用rollback()方法,数据库将自动放弃上一次提交事务以来的全部变化。一个数据库连接的缺省模式是autocommit模式,每个SQL命令一执行就会提交给数据库。一旦某个命令已提交,就不能把它退回。可以用Connect

19、ion接口的getAutocommit()方法,检验数据库的目前自动提交模式设置。用命令con.setAutoCommit(false)方法关闭自动提交模式。用mit()命令提交事务。用con.rollback()回滚一个事务。请看下例:import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;import javax.naming.NamingException;public class UseTran public UseTran() super();/*

20、 * param args */public static void main(String args) Connection con = null;/方法里临时变量要手动初始化 PreparedStatement updateAge=null; String updateString = update student + set age = ? where name like ?; String jndiname=jdbcPool/mydatasource; try con = DBCon.getConnectionFromPooledDataSource(jndiname); update

21、Age = con.prepareStatement(updateString); int age = 45, 39, 25, 96; String names = 梁朝伟%, 贝壳汗母%, 小罗%, 霍元甲%; int len = age.length; /设置事务提交模式 con.setAutoCommit(false); for (int i = 0; i len; i+) updateAge.setInt(1, agei); updateAge.setString(2, namesi); updateAge.executeUpdate(); /上面执行的语句,如果不出现异常则提交 SQ

22、L 语句 mit(); System.out.println(update success!); catch(NamingException ex) System.err.println(Name Not Bound : +ex.getMessage(); catch (SQLException ex) System.err.println(SQLException: + ex.getMessage(); if (con != null) try System.err.print(Transaction is being ); System.err.println(rolled

23、back); con.rollback();/如果出现异常则事务回滚 catch (SQLException excep) System.err.print(SQLException: ); System.err.println(excep.getMessage(); finally/不管发生不发生异常,要关闭连接,释放资源 try if(con!=null&updateAge!=null) updateAge.close(); con.close(); catch(Exception e) e.printStackTrace(); 事务的级别控制在SQL术语中,事务是逻辑工作单元(logic

24、al unit of work,LUW)构成的一个或多个语句。这在某种含义上意味着,一切都是事务。不过,通常而言,术语事务用来表示或全或无的系列操作;也就是说,要么一切十分成功,要么什么也没有发生。典型的事务是从银行帐户提款,并存放到另一个。只要提款完成,金额就消失了。另一个范例是复式薄记记帐法中的借方和贷方:借方和贷方都必须完成。在单用户模式,事务非常容易理解它们只是和保存或忘记应用程序的状态有关。在多用户模式中,事务变得复杂多了。多用户事务的经典说明是银行帐户,其中一个应用程序试图在借记帐户,同时另一个应用程序试图贷记同一个帐户。咱们在前面已经介绍过多线程编程(并发编程)。类似的,事务的根

25、本问题是保持两个事务相互隔离,否则一个应用程序就可能影响另一个,从而导致错误的程序状态。在我们简单的说明中,这可能意味着一个帐户中有错误的金额,这将无益于留住客户。当处理多个访问相同数据的用户时,通常可能出现三种问题:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。 不可重复读是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据

26、之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。 幻觉读是指当事务不是独立执行时发生的一种现象,例如 第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。为了解决与“多个线程请求相同数据”相关的问题,事务之间用锁相互隔开。多数主流的数据库支持不同类型的锁;因此,JDBC API支持不同类型的事务,它们由Connection对

27、象指派或确定。在JDBC API中可以获得下列事务级别:TRANSACTION_NONE 说明不支持事务TRANSACTION_READ_UNCOMMITTED说明在提交前一个事务可以看到另一个事务的变化。这样脏读,不可重复的读和虚读都是允许的。TRANSACTION_READ_COMMITTED说明读取未提交的数据是不允许的。这个级别仍然允许不可重复的读和虚读产生。TRANSACTION_REPEATABLE_READ说明事务保证能够再次读取相同的数据而不会失败,但虚读仍然会出现。TRANSACTION_SERIALIZABLE是最高的事务级别,它防止脏读,不可重复的读和虚读。为什么不是所有

28、事务都运行在TRANSACTION_SERIALIZABLE模式以保证最高程度的数据完整性呢?问题在于,和处理多线程编程有关的问题相似,事务保护的级别越高,性能损失就越大。假定您的数据库和JDBC驱动程序支持这个特性,则给定一个Connection对象,您可以明确地设置想要的事务级别:con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);您还可以确定当前事务的级别:int transactionIsolation = con.getTransactionIsolation(); if(transactionIsolat

29、ion = Connection.TRANSACTION_NONE)System.out.println(当前事务级别为:TRANSACTION_NONE。);参见程序:import java.sql.Connection;import java.sql.SQLException;import javax.naming.NamingException;public class TranTest public TranTest() super();/* * param args */public static void main(String args) String jndiname=jdbc

30、Pool/mydatasource; Connection con=null; try con = DBCon.getConnectionFromPooledDataSource(jndiname); int transactionIsolation = con.getTransactionIsolation(); if(transactionIsolation = Connection.TRANSACTION_NONE) System.out.println(当前事务级别为:TRANSACTION_NONE。); else if(transactionIsolation = Connecti

31、on.TRANSACTION_READ_COMMITTED) System.out.println(当前事务级别为:TRANSACTION_READ_COMMITTED。); else if(transactionIsolation = Connection.TRANSACTION_READ_UNCOMMITTED) System.out.println(当前事务级别为:TRANSACTION_READ_UNCOMMITTED。); else if(transactionIsolation = Connection.TRANSACTION_REPEATABLE_READ) System.out

32、.println(当前事务级别为:TRANSACTION_REPEATABLE_READ。); else if(transactionIsolation = Connection.TRANSACTION_SERIALIZABLE) System.out.println(当前事务级别为:TRANSACTION_SERIALIZABLE。); con.setAutoCommit(false); con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); transactionIsolation = con.getTransac

33、tionIsolation(); if(transactionIsolation = Connection.TRANSACTION_NONE) System.out.println(当前事务级别为:TRANSACTION_NONE。); else if(transactionIsolation = Connection.TRANSACTION_READ_COMMITTED) System.out.println(当前事务级别为:TRANSACTION_READ_COMMITTED。); else if(transactionIsolation = Connection.TRANSACTION_

34、READ_UNCOMMITTED) System.out.println(当前事务级别为:TRANSACTION_READ_UNCOMMITTED。); else if(transactionIsolation = Connection.TRANSACTION_REPEATABLE_READ) System.out.println(当前事务级别为:TRANSACTION_REPEATABLE_READ。); else if(transactionIsolation = Connection.TRANSACTION_SERIALIZABLE) System.out.println(当前事务级别为

35、:TRANSACTION_SERIALIZABLE。); catch(NamingException ex) System.err.println(Name Not Bound : +ex.getMessage(); catch(SQLException ex) System.err.println(SQLException : +ex.getMessage(); finally try if(con!=null) con.close(); catch(Exception e) e.printStackTrace(); System.out.println(程序执行结束!);使用存储过程 很多

36、数据库都支持在数据库内部执行的函数。这种方法有几个好处,包括更快的性能和改进的安全性。这些函数称为存储过程。存储过程是用来封装SQL语句来完成一个完整的业务功能,类似于面向对象里面方法的概念。虽然它们通常是用SQL编写的,但也可以用数据库支持的任何编程语言编写。随着Java语言日趋流行,几个数据库厂商-Oracle(Oracle数据库)和IBM(db2数据库)都起用了Java语言创建存储过程,还可以在不同数据库之间移动存储过程。 存储过程可以支持三种类型的参数:IN,OUT和INOUT,这对于存储过程在数据库内部真正能做什么来说,带来了很大的灵活性。不管存储过程是用什么语言编写的,它都能以一种

37、标准的方式从Java应用程序调用。 首先,您需要创建一个CallableStatement对象。为了标识存储过程和过程需要的参数的类型和数量,还要允许使用三种类型的调用。下面的清单说明了这三种类型(假定我们正在调用一个名为StudentList的存储过程): 1,call StudentList如果过程不需要参数 2,call StudentList(?,?)如果过程需要两个参数 3,?=call StudentList(?,?)如果参数需要两个参数并返回一个要想使用存储过程,首先应该创建一个存储过程!请看下例: import java.sql.Connection;import java.s

38、ql.SQLException;import java.sql.Statement;import javax.naming.NamingException;public class CreateStoredProceduresofSQLServer public CreateStoredProceduresofSQLServer() super();/* * param args */public static void main(String args) Connection con=null; Statement stmt=null; String jndiname=jdbcPool/my

39、datasource; try /建立数据连接 con = DBCon.getConnectionFromPooledDataSource(jndiname); /创建SQL语句 stmt = con.createStatement(); /1.创建存储过程show_students String createProcedure1 = create procedure show_students + as + select id, name,age + from students + order by id; stmt.executeUpdate( if exists(select name

40、from sysobjects + where name=show_studentsand type=p) + drop procedure show_students); stmt.executeUpdate(createProcedure1); /2.创建储存过程onestudent String createProcedure2 = create procedure onestudent + stu_id int = null, + name varchar(20) output, + age int output + as + if stu_id = null + BEGIN + PR

41、INT ERROR: You must specify a stu_id value. + RETURN + END + / Get the sales for the specified cof_name and + / assign it to the output parameter. + SELECT name = name, age = age + FROM coffees + WHERE id = stu_id + RETURN ; stmt.executeUpdate( if exists(select name from sysobjects + where name=ones

42、tudentand type=p) + drop procedure onestudent); stmt.executeUpdate(createProcedure2); /3.创建函数 String createProcedure3 = CREATE FUNCTION pubuse.ageofstu + /Input cof_name (stu_name varchar(20) + RETURNS int + /return sales AS + BEGIN + DECLARE age int + SELECT age = age + FROM student + WHERE name li

43、ke stu_name + RETURN age + END ; stmt.executeUpdate( if exists(select name from sysobjects + where name=ageofstu) + drop function pubuse.ageofstu); stmt.executeUpdate(createProcedure3); stmt.close(); con.close(); catch(NamingException ex) System.err.println(Name Not Bound : +ex.getMessage(); catch(S

44、QLException ex) System.err.println(SQLException : +ex.getMessage(); System.out.println(程序执行结束!);下面是使用存储过程的代码: import java.sql.CallableStatement;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Types;import javax.naming.NamingException;public class InvokeStoreProcdureofSQLServer public InvokeStoreProcdureofSQLServer() super();/* * param args */public static void main(String args) Connection con=null; String jndiname=jdbcPool/mydatasource

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论