JAVA完全控制Oracle中BLOB、CLOB说明

来源:互联网 发布:perl语言和python 编辑:程序博客网 时间:2024/05/16 16:00

原文出处:http://hi.baidu.com/elongskyscj/blog/item/7056d7dc71c5b5a0cc116656.html

 

网络上很多关于JAVA对Oracle中BLOB、CLOB类型字段的操作说明,有的不够全面,有的不够准确,甚至有的简直就是胡说八道。最近的项目正巧用到了这方面的知识,在这里做个总结。

环境:

Database: Oracle 9i

App Server: BEA Weblogic 8.14

表结构:

CREATE TABLE TESTBLOB (ID Int, NAME Varchar2(20), BLOBATTR Blob)

CREATE TABLE TESTBLOB (ID Int, NAME Varchar2(20), CLOBATTR Clob)

JAVA 可以通过JDBC,也可以通过JNDI访问并操作数据库,这两种方式的具体操作存在着一些差异,由于通过App Server的数据库连接池JNDI获得的数据库连接提供的java.sql.Blob和java.sql.Clob实现类与JDBC方式提供的不同,因 此在入库操作的时候需要分别对待;出库操作没有这种差异,因此不用单独对待。

一、BLOB操作

1、入库

(1)JDBC方式

     //通过JDBC获得数据库连接

     Class.forName("oracle.jdbc.driver.OracleDriver");

     Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:testdb", "test", "test");

     con.setAutoCommit(false);

     Statement st = con.createStatement();

     //插入一个空对象empty_blob()

     st.executeUpdate("insert into TESTBLOB (ID, NAME, BLOBATTR) values (1, "thename", empty_blob())");

     //锁定数据行进行更新,注意“for update”语句

     ResultSet rs = st.executeQuery("select BLOBATTR from TESTBLOB where ID=1 for update");

     if (rs.next())

     {

         //得到java.sql.Blob对象后强制转换为oracle.sql.BLOB

         oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob("BLOBATTR");

         OutputStream outStream = blob.getBinaryOutputStream();

         //data是传入的byte数组,定义:byte[] data

         outStream.write(data, 0, data.length);

     }

     outStream.flush();

     outStream.close();

     con.commit();

     con.close();

(2)JNDI方式

     //通过JNDI获得数据库连接

     Context context = new InitialContext();

     ds = (DataSource) context.lookup("ORA_JNDI");

     Connection con = ds.getConnection();

     con.setAutoCommit(false);

     Statement st = con.createStatement();

     //插入一个空对象empty_blob()

     st.executeUpdate("insert into TESTBLOB (ID, NAME, BLOBATTR) values (1, "thename", empty_blob())");

     //锁定数据行进行更新,注意“for update”语句

     ResultSet rs = st.executeQuery("select BLOBATTR from TESTBLOB where ID=1 for update");

     if (rs.next())

     {

         //得到java.sql.Blob对象后强制转换为weblogic.jdbc.vendor.oracle.OracleThinBlob(不同的App Server对应的可能会不同)

         weblogic.jdbc.vendor.oracle.OracleThinBlob blob = (weblogic.jdbc.vendor.oracle.OracleThinBlob) rs.getBlob("BLOBATTR");

         OutputStream outStream = blob.getBinaryOutputStream();

         //data是传入的byte数组,定义:byte[] data

         outStream.write(data, 0, data.length);

     }

     outStream.flush();

     outStream.close();

     con.commit();

     con.close();

2、出库

     //获得数据库连接

     Connection con = ConnectionFactory.getConnection();

     con.setAutoCommit(false);

     Statement st = con.createStatement();

     //不需要“for update”

     ResultSet rs = st.executeQuery("select BLOBATTR from TESTBLOB where ID=1");

     if (rs.next())

     {

         java.sql.Blob blob = rs.getBlob("BLOBATTR");

         InputStream inStream = blob.getBinaryStream();

         //data是读出并需要返回的数据,类型是byte[]

         data = new byte[input.available()];

         inStream.read(data);

         inStream.close();

     }

     inStream.close();

     con.commit();

     con.close();

二、CLOB操作

1、入库

(1)JDBC方式

     //通过JDBC获得数据库连接

     Class.forName("oracle.jdbc.driver.OracleDriver");

     Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:testdb", "test", "test");

     con.setAutoCommit(false);

     Statement st = con.createStatement();

     //插入一个空对象empty_clob()

     st.executeUpdate("insert into TESTCLOB (ID, NAME, CLOBATTR) values (1, "thename", empty_clob())");

     //锁定数据行进行更新,注意“for update”语句

     ResultSet rs = st.executeQuery("select CLOBATTR from TESTCLOB where ID=1 for update");

     if (rs.next())

     {

         //得到java.sql.Clob对象后强制转换为oracle.sql.CLOB

         oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob("CLOBATTR");

         Writer outStream = clob.getCharacterOutputStream();

         //data是传入的字符串,定义:String data

         char[] c = data.toCharArray();

         outStream.write(c, 0, c.length);

     }

     outStream.flush();

     outStream.close();

     con.commit();

     con.close();

(2)JNDI方式

     //通过JNDI获得数据库连接

     Context context = new InitialContext();

     ds = (DataSource) context.lookup("ORA_JNDI");

     Connection con = ds.getConnection();

     con.setAutoCommit(false);

     Statement st = con.createStatement();

     //插入一个空对象empty_clob()

     st.executeUpdate("insert into TESTCLOB (ID, NAME, CLOBATTR) values (1, "thename", empty_clob())");

     //锁定数据行进行更新,注意“for update”语句

     ResultSet rs = st.executeQuery("select CLOBATTR from TESTCLOB where ID=1 for update");

     if (rs.next())

     {

         //得到java.sql.Clob对象后强制转换为weblogic.jdbc.vendor.oracle.OracleThinClob(不同的App Server对应的可能会不同)

         weblogic.jdbc.vendor.oracle.OracleThinClob clob = (weblogic.jdbc.vendor.oracle.OracleThinClob) rs.getClob("CLOBATTR");

         Writer outStream = clob.getCharacterOutputStream();

         //data是传入的字符串,定义:String data

         char[] c = data.toCharArray();

         outStream.write(c, 0, c.length);

     }

     outStream.flush();

     outStream.close();

     con.commit();

     con.close();

2、出库

     //获得数据库连接

     Connection con = ConnectionFactory.getConnection();

     con.setAutoCommit(false);

     Statement st = con.createStatement();

     //不需要“for update”

     ResultSet rs = st.executeQuery("select CLOBATTR from TESTCLOB where ID=1");

     if (rs.next())

     {

         java.sql.Clob clob = rs.getClob("CLOBATTR");

         Reader inStream = clob.getCharacterStream();

         char[] c = new char[(int) clob.length()];

         inStream.read(c);

         //data是读出并需要返回的数据,类型是String

         data = new String(c);

         inStream.close();

     }

     inStream.close();

     con.commit();

     con.close();

需要注意的地方:

1、java.sql.Blob、oracle.sql.BLOB、weblogic.jdbc.vendor.oracle.OracleThinBlob几种类型的区别

2、java.sql.Clob、oracle.sql.CLOB、weblogic.jdbc.vendor.oracle.OracleThinClob几种类型的区别


  ===============================================================================


这些天一直在试图把一个用Oracle数据库做的项目转换为用msSql2000数据库的,本以为只要把数据库的连接池改改就可以了,没想到事实并没那么简单~ 要改的地方有好多,改了几天,也学了几天,今天又学到一个:在我的程序中有这样的SQL语句:

 sql = "insert into tab_publish_template(id, name, language, content, filename, editor, editime, priority, remark) "
           + " values(" + myId + ","
           + "'" + Common.toSql(myName) + "',"
           + "'" + Common.toSql(myLanguage) + "'," 
           + "empty_clob(),"
           + "'N/A',"
           + "'" + Common.toSql(myEditor) + "',"
           + "SYSDATE,"
           + myPriority + ","
           + mySqlRemark
           + ")";
 stmt.executeUpdate(sql);
 //处理CLOB型数据  --- oracle 数据库
       sql = "select content from tab_publish_template where id=" + myId + " for update";
       rs = stmt.executeQuery(sql); 
       if (rs.next()) 
       ...{ 
             //oracle.sql.CLOB clob = (oracle.sql.CLOB)rs.getClob("content");
             String clob = rs.getString("content");
             clob.putString(1, myContent);
             sql = "update tab_publish_template set content=? where id=" + myId;
             PreparedStatement pstmt = conn.prepareStatement(sql);
             pstmt.setClob(1, clob);
             pstmt.executeUpdate();
             pstmt.close();
       }
       rs.close();
       rs = null;
  没有看懂 empty_clob() 这个是干什么的,在原来的oracle 数据库脚本中找到content 字段的类型是 clob  型的,只看脚 本,我只能理解是这个字段重要放很多,很长的数据,要足够大,于是就想在sql2000 中找到同样的字段类型,但是很不幸:没得~    于是就搜了一 大堆资料出来~ 最后也看个一知半解得了吧~  贴上来,给需要的朋友一起讨论:(采用)

 一、请问clob   和blob是什么意思? 

 答:1,他们都是oracle数据库中的大对象数据类型,oracle提供专门的包对其操作。

         2,blob、clob、nclob   三种大型对象(LOB),用来保存较大的图形文件或带格式的文本文件,如Miceosoft   Word文档,以及音频、视频等非文本文件,最大长度是4GB。   

         LOB有几种类型,取决于你使用的字节的类型,Oracle   8i实实在在地将这些数据存储在数据库内部保存。   
   可以执行读取、存储、写入等特殊操作   
     
        CLOB(Character   Large   Object)    用于存储对应于数据库定义的字符集的字符数据。(类似于long类型)   
     
         BLOB(Binary   Large   Object)   可用来存储无结构的二进制数据。(类似于row和long   row)

 二、请问LOB的BLOB、CLOB、BFILE有什麽区别,都用在什麽情况?怎样操作?

 答:

 BLOB   ——内部二进制大对象。   
 CLOB  ——内部字符大对象。   
 NCLOB   ——内部定长多字节字符大对象。   
 BFILE   ——外部二进制文件。      
   LOB   由两部分组成:数据(值)和指向数据的指针(定位器)。尽管值与表自身一起存储,但是一个LOB 列并不包含值,仅有它的定位指针。更进一步,为了使用大 对象,程序必须声 明定位器类型的本地变量。你将在本章后面见到P   L   /   S   Q   L   接口使用定位器如同操作系统的文件 处 理一样。当LOB(除了BFILE  )被创建时,定位器被存放在列中,值被存放在LOB 段中,  LOB  段是在数据库内部表的一部分。当 BFILE  被创建时,定位器如同平常一样存储在列中

 三、blob和clob最大是多少?还是没有最大限制?

 答:它们的最大上限就是4G,   Clob可以存储单字节字符数据,Blob可以存储无结构的二进制数据

 [附加]  不想另开一篇了,就加在这里了,一个关于SQL2000的问题
 sql2000中某字段长度不够为何会填上空格?

  答:sql2000中char型是固定长度的,如固定长度为10,但是只录入了3个字符,那么剩下7位就要补充空格来填满。如果,你不想让他自动补充空 格,可以选用varchar型,这个是实际长度,也很好用,速度也快,PS:oracle中如果可以用varchar2的地方就不要用clob ,因为后 者的速度确实不怎么好。


 

=================================================================================


 

不知道是坛子里的高手都不屑于回答这么弱智的问题还是都没人关注oracle xmltype.自己搞定了,贴出来给象我一样盲目的朋友.
以前我的客户端是9i,所以装了10g的odp.net,发现冲突,捣腾了很久才卸掉,重装了9i,发现PL/SQL里edit data总是很慢,根本出不来xmltype的数据行,后来才知道是版本问题,
装了10g的客户端就好了,而且odp.net也有了。
using Oracle.DataAccess.Types;
using Oracle.DataAccess.Client;

第一步:将xml文件读成string型:
StreamReader sr = new StreamReader("E://my.net//oracleXmlTest//mcc.xml");
  string outstring = ""; 
                // Read and display lines from the file until the end of 
                // the file is reached.
             while ((line = sr.ReadLine()) != null)
             {
                 outstring += line;
             }
或者直接:
  XmlDocument xDocument = new XmlDocument();
  xDocument.Load("E://my.net//oracleXmlTest//mcc.xml");
第二步:定义OracleXmlType
     // OracleXmlType cxml = new OracleXmlType(conn, outstring);
       OracleXmlType cxml = new OracleXmlType(conn, xDocument);
第三步:
 OracleConnection conn = new OracleConnection("Data Source=GISORA;User 

Id=meng;Password=meng");
conn.Open();
 OracleCommand cmd = new OracleCommand();
 cmd.Connection = conn;
 cmd.CommandText = "INSERT INTO resumes4 VALUES (15,:pb)";
 cmd.Parameters.Add("pb", OracleDbType.XmlType, iSize).Value = cxml;
 cmd.ExecuteNonQuery();            
 conn.Close();
代码很简单,过程很艰难!

 


原创粉丝点击