注册 | 登录 忘记密码? 51cto首页 | 博客 | 论坛 | 招聘
热点文章 你会划分和聚合子网吗?
 帮助

大字段的存取


2007-07-11 23:07:32
 标签:存取   [推送到技术圈]

Oracle的Blob字段比较特殊,他比long字段的性能要好很多,可以用来保存例如图片之类的二进制数据。    
   
  写入Blob字段和写入其它类型字段的方式非常不同,因为Blob自身有一个cursor,你必须使用cursor对blob进行操作,因而你在写入Blob之前,必须获得cursor才能进行写入,那么如何获得Blob的cursor呢?    
   
  这需要你先插入一个empty的blob,这将创建一个blob的cursor,然后你再把这个empty的blob的cursor用select查询出来,这样通过两步操作,你就获得了blob的cursor,可以真正的写入blob数据了。    
   
  看下面的JDBC的demo,把oraclejdbc.jar这个二进制文件写入数据库表javatest的content字段(这是一个blob型字段)    
   
  java代码:      
   
  import   java.sql.*;    
  import   java.io.*;    
  import   oracle.sql.*;    
  public   class   WriteBlob   {    
   
      public   static   void   main(String[]   args)   {    
   
          try   {    
              DriverManager.registerDriver(new   oracle.jdbc.driver.OracleDriver());    
              Connection   conn   =   DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl","fankai","fankai");    
              conn.setAutoCommit(false);    
   
              BLOB   blob   =   null;    
   
              PreparedStatement   pstmt   =   conn.prepareStatement("insert   into   javatest(name,content)   values(?,empty_blob())");    
              pstmt.setString(1,"fankai");    
              pstmt.executeUpdate();    
              pstmt.close();    
   
              pstmt   =   conn.prepareStatement("select   content   from   javatest   where   name=   ?   for   update");    
              pstmt.setString(1,"fankai");    
              ResultSet   rset   =   pstmt.executeQuery();    
              if   (rset.next())   blob   =   (BLOB)   rset.getBlob(1);    
   
              String   fileName   =   "oraclejdbc.jar";    
              File   f   =   new   File(fileName);    
              FileInputStream   fin   =   new   FileInputStream(f);    
              System.out.println("file   size   =   "   +   fin.available());    
   
              pstmt   =   conn.prepareStatement("update   javatest   set   content=?   where   name=?");    
   
              OutputStream   out   =   blob.getBinaryOutputStream();    
   
              int   count   =   -1,   total   =   0;    
              byte[]   data   =   new   byte[(int)fin.available()];    
              fin.read(data);    
              out.write(data);    
              /*    
              byte[]   data   =   new   byte[blob.getBufferSize()];     另一种实现方法,节省内存    
              while   ((count   =   fin.read(data))   !=   -1)   {    
                  total   +=   count;    
                  out.write(data,   0,   count);    
              }    
              */    
   
              fin.close();    
              out.close();    
   
              pstmt.setBlob(1,blob);    
              pstmt.setString(2,"fankai");    
   
              pstmt.executeUpdate();    
              pstmt.close();    
   
              conn.commit();    
              conn.close();    
          }   catch   (SQLException   e)   {    
              System.err.println(e.getMessage());    
              e.printStackTrace();    
          }   catch   (IOException   e)   {    
              System.err.println(e.getMessage());    
          }    
      }    
   
  }  
     
   
   
   
   
  仔细看上例,分三步:    
   
  1、插入空blob    
  into   javatest(name,content)   values(?,empty_blob());    
   
  2、获得blob的cursor    
  select   content   from   javatest   where   name=   ?   for   update;    
   
  注意!!!必须加for   update,这将锁定该行,直至该行被修改完毕,保证不产生并发冲突。    
   
  3、update   javatest   set   content=?   where   name=    
   
  用cursor往数据库写数据    
   
  这里面还有一点要提醒大家:    
   
  JDK1.3带的JDBC2.0规范是不完善的,只有读Blob的接口,而没有写Blob的接口,JDK1.4带的JDBC3.0加入了写Blob的接口。你可以使用JDBC3.0的接口,也可以直接使用Oracle的JDBC的API,我在上例中使用了Oracle的JDBC的API。    
   
  另外要注意的是:    
   
  java.sql.Blob    
  oracle.sql.BLOB    
   
  注意看blob的大小写,是不一样的。写程序的时候不要搞混了。    
   
  下面看看用Hibernate怎么写,原理是一样的,也要分三步,但是代码简单很多    
   
  这是Cat对象定义    
  java代码:      
   
  package   com.fankai;    
   
  import   java.sql.Blob;    
   
  public   class   Cat   {    
      private   String   id;    
      private   String   name;    
      private   char   sex;    
      private   float   weight;    
      private   Blob   image;    
      public   Cat()   {   }    
   
      public   String   getId()   {   return   id;   }    
      public   void   setId(String   id)   {   this.id   =   id;   }    
   
      public   String   getName()   {   return   name;   }    
      public   void   setName(String   name)   {   this.name   =   name;   }    
   
      public   char   getSex()   {   return   sex;   }    
      public   void   setSex(char   sex)   {   this.sex   =   sex;   }    
   
      public   float   getWeight()   {   return   weight;   }    
      public   void   setWeight(float   weight)   {   this.weight   =   weight;   }    
       
      public   Blob   getImage()   {   return   image;   }    
      public   void   setImage(Blob   image)   {   this.image   =   image;}    
  }  
     
   
   
  这是Cat.hbm.xml    
   
  java代码:      
   
  <?xml   version="1.0"?>    
  <!DOCTYPE   hibernate-mapping   SYSTEM   "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">    
   
  <hibernate-mapping>    
          <class   name="com.fankai.Cat"   table="cat">    
                  <!--jcs-cache   usage="read-only"/-->    
                  <id   name="id"   unsaved-value="null">    
                          <generator   class="uuid.hex"/>    
                  </id>    
                  <property   name="name"   length="16"   not-null="true"/>    
                  <property   name="sex"   length="1"   not-null="true"/>    
                  <property   name="weight"   />    
                  <property   name="image"   />    
          </class>    
  </hibernate-mapping>  
     
   
   
   
  下面是完整的用Hibernate写入Blob的例子,相比JDBC,已经简单轻松多了,也不用写那些Oracle特殊的sql了:    
   
  java代码:      
   
  package   com.fankai;    
   
  import   java.sql.Blob;    
  import   net.sf.hibernate.*;    
  import   oracle.sql.*;    
  import   java.io.*;    
   
  public   class   TestCatHibernate   {      
      public   static   void   testBlob()   {    
          Session   s   =   null;          
          byte[]   buffer   =   new   byte[1];    
          buffer[0]   =   1;    
          try   {    
              SessionFactory   sf   =   HibernateSessionFactory.getSessionFactory();    
              s   =   sf.openSession();      
              Transaction   tx   =   s.beginTransaction();    
              Cat   c   =   new   Cat();    
              c.setName("Robbin");    
              c.setImage(Hibernate.createBlob(buffer));    
              s.save(c);    
              s.flush();    
              s.refresh(c,   LockMode.UPGRADE);          
              BLOB   blob   =   (BLOB)   c.getImage();              
              OutputStream   out   =   blob.getBinaryOutputStream();          
              String   fileName   =   "oraclejdbc.jar";    
              File   f   =   new   File(fileName);    
              FileInputStream   fin   =   new   FileInputStream(f);          
              int   count   =   -1,   total   =   0;    
              byte[]   data   =   new   byte[(int)fin.available()];    
              fin.read(data);    
              out.write(data);              
              fin.close();    
              out.close();    
              s.flush();    
              tx.commit();    
           
          }   catch   (Exception   e)   {    
              System.out.println(e.getMessage());    
          }   finally   {    
              if   (s   !=   null)    
                  try   {    
                      s.close();    
                  }   catch   (Exception   e)   {}    
          }          
           
      }    
  }  




    文章评论
 
 

发表评论

昵   称:
验证码:  点击图片可刷新验证码  博客过2级,无需填写验证码
内   容: