⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 day03.txt

📁 JDBC描述详解JDBC描述详解JDBC描述详解JDBC描述详解
💻 TXT
字号:
JDBC_day03   langna  2007-9-10   星期一

一、事务并发:
    事务并发:事务和事务之间有时间重合的地方;
    并发:
    1、必须的;
    2、产生某些不良的后果;
    3、某些手段来控制;
    从效率上来说,并发是必须的;但是不良的后果得消除;
    
    三种后果:
    1、脏读(dirty read):
                  dirty data;修改了一半的数据,还没有提交;
                  一个事务读到了另一个事务没有提交的数据;
        
         事务a:存100;1000  +  100  --> 1100(未提交)--> rollback; --->1000
                                                事务b:     1100+200---> 1300----> commit; 造成数据不一致;
         后果很严重;大多数数据库将防止脏读,作为默认的控制级别;
         
     2、不可重复读(UnRepeatable Read):
                 一个事务在事务期间,前后对同一组数据进行读操作,读到的结果不一致;
                 原因是:在这个事务两次读的中间,有其他事务提交了数据;
                 与脏读不同的是 :读的是已提交的数据;
                 (update)
          事务a: 存100;1000+100--> 1100--> 提交时先读一下,跟1000不同了,不能存1100了;
                                                                    如果仍存上1100,就是更新(1200)丢失;
          在a持续的期间:事务b: 存200;1000+200--> 提交 :1200 
          
          对于即时改变的东西(天气预报)没关系,但是对于累加的东西(银行帐户)不能出现更新丢失的情况;
      3、幻读(phantom  read):
                  在一个事务的执行期间,前后两次读同一组数据,数据量不一致;记录个数增加或减少;
                  (insert)
                  银行统计:
                  10万个帐户,-->  余额 :10亿 
                  存的时候又变成:100100个帐户;
                  商场盘点:关门进行;
                  
二、事务隔离级别:

    TRANSACTION_NONE   不使用事务。没有什么用;只是理论上的,实际无意义;
    TRANSACTION_READ_UNCOMMITTED  没有控制;可以读取未提交数据。也无实际意义;
    TRANSACTION_READ_COMMITTED   可以避免脏读,不能够读取没提交的数据,
                                                                最常用的隔离级别,大部分数据库的默认隔离级别;
    TRANSACTION_REPEATABLE_READ  可以避免脏读,和不可重复读;
    TRANSACTION_SERIALIZABLE   可以避免脏读,重复读取和幻读,
                                                      (事务串行化)会降低数据库效率
                                                      
    后两种在很多数据库中是没有区别的;防止提交别的数据,即不让别的事务操作,
    一个事务一个事务串行执行;小范围内没有并发;效率低;
    用的不多;一般是在代码中控制;
    
    Oracle:就支持两种,防止脏读和串行化;
    
    以上的五个事务隔离级别都是在Connection类中定义的静态常量,
    使用setTransactionIsolation(int level) 方法可以设置事务隔离级别。
    
三、JDBC新特性:
      四、五、六章是2.0的扩展;
      对resultset的扩展
      对statement的增强(批处理)
      sql3.0类型(blob/clob)
      datasource(jndi)
      rowset
      
1、JDBC2.0 ResultSet 可滚动结果集(可双向滚动),这种结果集不但可以双向滚动,
     相对定位,绝对定位,并且可以修改数据信息。
     
    滚动特性
    next(),boolean,此方法是使游标向下一条记录移动。(向最后一条记录的方向移动)
    previous() ,此方法可以使游标上一条记录移动,前提前面还有记录。(向第一条记录的方向移动)
    absolute(int row),boolean ,可以使用此方法跳到指定的记录位置。
                             定位成功返回true,不成功返回false,返回值为false,则游标不会移动。
    afterLast() ,void  游标跳到最后一条记录之后。
    beforeFirst() ,void 游标跳到第一条记录之前。(跳到游标初始位)
    first(),boolean,游标指向第一条记录。
    last(),boolean ,游标指向最后一条记录。
    relative(int rows) ,相对移动的位置个数,参数值可正可负,参数为正,
                                游标从当前位置向下移动指定值,参数为负,
                                游标从当前位置向上移动指定值。
   
    TYPE_FORWARD_ONLY ,该常量指示指针只能向前移动的 ResultSet 对象的类型。 
        
    TYPE_SCROLL_INSENSITIVE ,该常量指示可滚动但通常不受其他的更改影响的 ResultSet 对象的类型。 
    TYPE_SCROLL_SENSITIVE ,该常量指示可滚动并且通常受其他的更改影响的 ResultSet 对象的类型。
                                              
                                              有的数据库支持,有的不支持;
                                              我们用哪个都可以,只要支持可滚动的
    CONCUR_READ_ONLY ;//只读结果集
    CONCUR_UPDATABLE; //可更新结果集,可以通过结果集来更新数据库;用在小应用中;快速开发;
   
   在驱动程序支持2.0特性的情况下,会给你一个你要的结果集类型:
   
    要使用可滚动结果集时,要在Statement创建时指定两个参数,才可以使用
    Statement st=null;
    st=con.createStatement(ReusltSet.TYPE_SCROLL_INSENSITIVE,ResuleSet.CONCUR_UPDATABLE);
    
    
    PreparedStatement ps-null;
    ps=con.PrepareStatement("select * from t_test",ResultSet.TYPE_SCROLL_INSENSITIVE,
                                           ResuleSet.CONCUR_READ_ONLY);//顺序不能颠倒,否则编译可过,运行会报错;
    rs=ps.executeQuery();
    JdbcUtil.printRs(rs);//这时候游标已经指向最后一条记录的后边了;
    if(rs.isAfterLast()){sysout("最后一条记录的后边 ");}
    
    rs.beforeFirst();//移动到前边
    sysout("-----------------------");
    JdbcUtil.printRs(rs);
    
    CONCUR_UPDATABLE; //增删改都可以;
    1) 更新
    移到要更新的记录处:rs.absolute(3);
    rs.updateInt(1,"1243535");
    rs.updateString("name","tony");
    rs.updateRow();//提交一下
   2) 删除
   rs.absolute(10);
   rs.deleteRow();
   3) 插入 
    a.  rs.moveToInsertRow();//1、先把游标移动到插入缓冲区;跟结果集结构一样;并且把游标本来的位置记住;
    -----------------插入数据,b,c 可以重复
    b.  rs.updateInt(1,"1243535");//2、填充缓冲区
        rs.updateString("name","tony");
    c.  rs.insertRow();//3、将缓冲区的内容放到数据库中;
    -----------------
    b.  rs.updateInt(1,"1243535");
         rs.updateString("name","tony");
    c.  rs.insertRow();//3、将缓冲区的内容放到数据库中;
    ----------------
    d. rs.moveToCurrentRow();//4、将游标移回到原来的位置;
   
    支持不支持可更新结果集 得看数据库的驱动;
    还有别的限制:下午讲;
    1)对于Oracle用可更新的结果集:
    select id,name from t_test;//不能用通配符select  * from  t_test;
    2)查询只能引用一张表;
    3)不能有join操作;不能用order by 等其他操作;
    4)会取所有非空字段且没有默认值;
    5)插入结果集是无序的;
    
    记住做完修改的操作后,要提交后再从数据库中读一次结果集才能看到修改的结果;

2、批处理更新  
    一般是20~50~100,会提高效率;
     1)   Statement
        addBatch(String sql), 方法会在批处理缓存中加入一条sql语句
        executeBatch() ,执行批处理缓存中的所有sql语句。
        
     2)   PreparedStatement
          ps = con.prepareStatement(
			  "insert into t_test  values(?,?)");
          
		  for(int i=0;i<50;i++){
		     ps.setInt(1,999801+i);
		     ps.setString(2,"batch");
		     ps.addBatch();
		  }
		  ps.executeBatch();
		  con.commit();
		  
        addBatch() 将一组参数添加到此 PreparedStatement 对象的批处理命令中。
        
        executeBatch() 将一批命令提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组。
        PreparedStatement中使用批量更新时,要先设置好参数后使用addBatch()方法加入缓存。
        注意:批量更新中只能使用更新或插入语句
        
        execute(String sql),这个方法的返回值是boolean类型,
        如果返回true就表示sql是一个select语句,
        可以通过getResultSet()获得结果集,
        如果是false,sql就是DML语句或者是DDL语句。

3、 SQL3.0 (SQL99)中的类型

    Array,数组 创建一个数组名为ints的有10个元素的数组,元素的类型为number(4);
                create type ints as  Array(10) of number(4);
                create table numbers(values  ints);
                数据库类型:ARRAY;  数据库中的类型;ARRAY a=((OracleResultSet)rs.getARRAY(1));//这种基本不用了;
                1) jdbc类型:java.sql.Array;Array a=rs.getArray(1);//
                2) java类型:BigDecimal[] values=(BigDecimal[])a.getArray();//将Object[]转成你想要的类型;
    Sturct,结构
           create type money as numberic(10,2);
    Ref, 引用;用的很少;
    
    Blob,大的二进制数据文件。Binary large object 
    Clob,大文本文件对象。       Character  large object
   
   以前处理大对象:有大小上限;是固定的,虽然可调大小;
                              读的方式:一次性读取,要么全读走,要么不读;rs;
       Blob: 
       1)理论上大小不限;
       2)流式读取;(是引用)读的时候才传过来;
       往数据库中存blob数据:
       con.setAutoCommit(false);
       //1、委托oracle替我们制造一个空的Blob字段,empty_blob();是oracle的函数
       ps=con.prepareStatement("insert into t_blob values(?,?,empty_blob())");
       
       //2、将空的Blob对象读回来;
       JdbcUtil.close(ps);//释放资源
       ps=con.prepareStatement("select blobData from t_blob where id=? for update");
       //for update,加一个读锁;防止别的事务修改;
       //游标变成可写的,普通的结果集的sql加for update 就可以改字段的值;
       
       rs=ps.executeQuery();
       rs.next();
       Blob blob=rs.getBlob(1);
       
       //3、打开一个文件输入流(读),打开一个blob上的输出流(写),将文件内容写入blob对象;
       InputStream in=new FileInputStream(fname);
       OutputStream out=blob.setBinaryStream(0);//0是下标,设置从流的第一个字节写;
       byte[] content =new byte[in.available()];//将文件中的所有字节写到一个字节数组里
       in.read(content);
       out.write(content);
       in.close();
       out.close();
       
       //4、将写满数据的blob对象更新回数据库
       ps=con.prepareStatement("update t_blob set blobData=? where  id=?");
       ps.setBlob(1,blob);
       ps.setInt(2,100);
       ps.executeUpdate();
       
       con.commit();
      
      create table ln_blob(id number(10) primary key,filename varchar2(20),blobData blob);    
      insert into ln_blob  values(100,null,null);
     
      不能用sqlplus检索blob字段;select * from ln_blob;//是不能用的;
       
    从数据库中读blob数据:
     
		 //1.读blob值
                 ps = con.prepareStatement(
		  "select blobdata from t_blob where fname=?");
		 ps.setString(1,fname);
		 rs = ps.executeQuery();
                 rs.next();
		 blob = rs.getBlob(1);
		 //2.将blob值写入文件
		 OutputStream out = new FileOutputStream(fname);
		 InputStream in = blob.getBinaryStream();
		 int b = 0; int c = 0;int x=0;
		 while((b=in.read())!=-1){
		   if((++c%1024)==0){
			 System.out.println("here we go ..."+(++x)+"kb");
		   }
		   out.write(b);
		 }
		 in.close();out.close();
	   }catch (Exception ex){
		 ex.printStackTrace();
	   }finally{
	     JdbcUtil.close(rs,ps,con);
	   }
  }
       
   
    
   
   
    
    
                                                            
    
    
     

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -