最近在J2EE的项目中需要使用LOB字段保存文本信息以及图片和文件,到网上搜拉一下,还不少,仔细看拉一下,但都不是很全有的还有错误,经过几天的实践,把问题都解决拉,顺便总结一下,希望对需要的朋友有点参考 
LOB中我们用的比较多的主要有两种CLOB和BLOB,我们对两种类型分别讨论 
1.CLOB是字符型LOB,主要存储文本信息,,最长为4G.,在J2EE程序中,比如网页的textarea中的字符信息比较长,Varchar2字段类型不能满足时,我们就得用CLOB数据类型,我们这次项目中就碰到这种情况.现在我们先说说如何存取CLOB字段 
现在我要把网页中的textarea元素的信息保存到数据库的CLOB字段中, 我们都知道textarea中的信息当然不能直接保存成CLOB,我们在后台得到的是String类型的,不多说拉,我们还是以一个实例讲吧! 
先建一个test表,表有2个字段:ID,CONTENTS,其中CONTENTS保存CLOB类型的文本数据 
create table TEST (   ID         VARCHAR2(18) not null,   CONTENTS   CLOB,  ) 
接着我们编写一个测试用的jsp文件ClobTest.jsp,代码如下
 
  
<%@ page language="java" contentType="text/html; charset=gb2312" %> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=gb2312"> 
<title>Clob对象的存取测试</title> 
</head> 
  
<body> 
<form name="test" method="post" action="clobTest.action"> 
  <table width="80%" height="88"  border="0" align="center" cellpadding="0" cellspacing="0"> 
    <tr> 
         <td height="30" align="center">输入ID号<input type="text" name="ID"> 
    </tr> 
    <tr> 
      <td align="center"> 
 <textarea rows="28" cols="68" name="CONTENTS"> 
注册用户需遵守: 
     尊重会员个人隐私、保障会员隐私安全是CSDN的一项基本政策,CSDN不会公开、编辑或透露会员的注册资料,除非符合以下情况:     (1) 根据中华人民共和国国家安全机构、公安部门的要求及根据相应的法律程序要求。     (2) 维护CSDN的商标所有权及其它权益。     (3) 在紧急情况下竭力维护会员个人、其它社会个体和社会大众的安全。     (4) 严重违反CSDN有关规定。     CSDN保留结束会员使用网络服务资格的权利,并保证结束会员资格后仍为会员保密所有个人隐私。 
      </textarea>     
         </td> 
    </tr> 
       <tr> 
          <td align="center"> 
           <input type="submit" name="Submit" value="提交"> 
          </td> 
       </tr> 
  </table> 
</form> 
</body> 
</html> 
点击”提交”按钮,我们在后台的到的是2个String类型的对象 
String strID = request.getParameter(“ID”); 
String strCONTENTS = request.getParameter(“CONTENTS”); 
接着我们要做的任务就是如何把String类型CONTENTS存到数据库中的CLOB类型字段中! 
注意:LOB数据不能象其它类型数据一样直接插入(INSERT)。插入前必须先插入一个空的LOB对象,CLOB类型的空对象为EMPTY_CLOB(),BLOB类型的空对象为EMPTY_BLOB()。之后通过SELECT命令查询得到先前插入的记录并锁定,继而将空对象修改为所要插入的LOB对象。 
//我们先插入一个空的CLOB对象 
  public int insertEmptyClob() throws Exception { 
    Statement statement = null; 
    int intResult = -1; 
    try { 
      //创建数据库操作语句 
statement = connection.createStatement(); 
//定义SQL语句 
String strSQL = “INSET INTO TEST (ID,CONTENTS) VALUES(strID, EMPTY_CLOB())”; 
      //执行SQL语句 
      intResult = statement.executeUpdate(strSQL); 
System.out.println(" intResult valus is"+intResult); 
      return intResult; 
    } catch(Exception e) { 
      e.printStackTrace(); 
      return -1; 
    } finally { 
      if (statement != null) { 
        statement.close(); 
      } 
    } 
  } 
//把strCONTENT插入CLOB字段 
  public void insertClob() throws Exception { 
    Statement statement = null; 
    ResultSet resultset = null; 
    try { 
      //设置不自动提交 
      connection.setAutoCommit(false); 
      //创建数据库操作语句 
statement = connection.createStatement(); 
//定义SQL语句 
String strSQL = “SELECT CONTENTS  FROM TEST  WHERE ID=strID"” 
      resultset = statement.executeQuery(strSQL); 
      oracle.sql.CLOB contents = null; 
      while(resultset.next()) { 
        //取出CLOB对象 
        contents = (oracle.sql.CLOB)resultset.getClob("CONTENTS"); 
      } 
      Writer out = contents.getCharacterOutputStream(); 
      out.write(strContents); 
      out.flush(); 
out.close(); 
//数据库提交 
      connection.commit(); 
    } catch(Exception e) { 
      e.printStackTrace(); 
    }finally{ 
      if(resultset != null) { 
        resultset.close(); 
      } 
      if(statement != null) { 
        statement.close(); 
      } 
    } 
  } 
OK,我们已经把这段文本以CLOB字段的形式保存到数据库中了,在实际应用中,如果要保存或修改一条记录,我们要分2步做,先保存或修改非LOB字段类型的字段,再保存或修改LOB字段!接下来我们来把刚才保存到数据库中的CLOB字段读到jsp页面中去。 
我们在保存的时候,CLOB字段会把上面textarea中的文本按原来的格式一行一行(包括空格)都保存到CLOB字段中,读取的时候我们只要按照原来格式读起出来就行了(我这里自己用了一个小处理方法,但如果你有更好的方法请告诉我)。在这里我们把CLOB读到StringBuffer中,为了保存不同行我在行之间加了个“&”字符来区分。最后转化成String 
放到VO中,这样就保证从前台到后台,从后台到前台的数据传递的一致性!代码如下: 
  
  
  
  /** 
   * 获取CLOB文本对象 
   * @param sbSQL 
   * @return 
   * @throws java.lang.Exception 
   */ 
  public String selectIncludeClob(StringBuffer sbSQL) throws Exception { 
    Statement stmt = null; 
    ResultSet rs = null; 
    StringBuffer sbResult = new StringBuffer(); 
    try { 
      //设定数据库不自动提交 
      //connection.setAutoCommit(false); 
      //创建数据库操作语句 
      stmt = connection.createStatement(); 
      //获取结果集 
      rs = stmt.executeQuery(sbSQL.toString()); 
  
      while(rs.next()) { 
        CLOB clob = (CLOB)rs.getClob("CONTENTS"); 
        Reader isClob = clob.getCharacterStream(); 
        BufferedReader bfClob = new BufferedReader(isClob); 
        String strClob = bfClob.readLine(); 
        while(strClob != null) { 
          sbResult.append(strClob); 
          sbResult.append("&"); 
          strClob = bfClob.readLine(); 
        } 
      } 
      //提交事务 
     // connection.commit(); 
    } catch(Exception e) { 
      e.printStackTrace(); 
      throw e; 
    } finally { 
      if(rs != null) { 
        rs.close(); 
      } 
      if(stmt != null) { 
        stmt.close(); 
      } 
    } 
    return sbResult.toString(); 
  } 
到jsp页面中,我们从VO中获取改文本信息。 
<textarea rows="42" cols="68" name="CONTENTS" style="border-style: solid; border-color: #FFFFFF; font-family:仿宋_GB2312; font-size:14pt; line-height:200%; margin-top:8; margin-bottom:6" > 
<% 
  String content = vo.getContent(); 
  String[] contentArray = content.split("&"); 
  for(int i=0;i<contentArray.length;i++) { 
  String s= contentArray[i]; 
  out.println(s); 
  }   
%>   
</textarea> 
这样我们就保证什么格式保存就以什么格式显示。 
2.BLOB字段,二进制LOB,主要存储二进制数据,最长为4G,在J2EE程序中,一般类似于图片和文件的保存。当然也有另一种方法,就把图片和文件保存在硬盘上,数据库中只保存图片的链接地址和文件在服务器上的路径。如果遇到文件和图片比较重要的还是需要保存到数据库中(例如:我们做国土资源项目的时候,好多图片、文件就很重要,需要保存到数据库中),下面我写一个保存文件到数据库的Blob字段和从数据库的Blob字段中获取文件的方法(当然完全应用还要做其他工作,这里就不多说了,如果你不清楚的可以问我): 
/** 
 * 把上传的文件保存到数据库的Blob字段中 
 * @param strTableName 对应的表名称 
 * @param strColumnName 表中保存文件的Blob字段名称 
 * @param inputStream   输入的文件流 
 * @param sbSQLWhere  where条件 
 * @throws java.lang.Exception 
 */ 
  public static void fileUpload(String strTableName, 
                                String strColumnName, 
                                InputStream  inputStream, 
                                StringBuffer sbSQLWhere) 
      throws Exception { 
    Connection con         = null; 
    ResultSet  resultset   = null; 
    Statement stmt         = null; 
  try { 
    //得到数据库连接 
    con = DBConnector.getConnection(); 
    //构建查询语句 
    StringBuffer sbSQL = new StringBuffer(); 
    sbSQL.append(" UPDATE "); 
    sbSQL.append(strTableName); 
    sbSQL.append(" SET "); 
    sbSQL.append(strColumnName); 
    sbSQL.append("=EMPTY_BLOB() "); 
    sbSQL.append(sbSQLWhere); 
    System.out.println(" update sql value is*******"+sbSQL.toString()); 
    //获取数据库操作语句 
    stmt=con.createStatement(); 
    //插入空的blob对象 
    stmt.executeUpdate(sbSQL.toString()); 
    con.setAutoCommit(false); 
    StringBuffer sbSQLBlob = new StringBuffer(); 
    sbSQLBlob.append(" SELECT "); 
    sbSQLBlob.append(strColumnName); 
    sbSQLBlob.append(" FROM "); 
    sbSQLBlob.append(strTableName); 
    sbSQLBlob.append(sbSQLWhere); 
    sbSQLBlob.append(" FOR UPDATE"); 
    System.out.println(" select sql value is*********"+sbSQL.toString()); 
    resultset =stmt.executeQuery(sbSQLBlob.toString()); 
    while (resultset.next()) { 
      /* 取出此BLOB对象 */ 
      oracle.sql.BLOB blob = (oracle.sql.BLOB)resultset.getBlob("BODY"); 
      /* 向BLOB对象中写入数据 */ 
      BufferedOutputStream out = new BufferedOutputStream(blob.getBinaryOutputStream()); 
      BufferedInputStream in = new BufferedInputStream(inputStream); 
      int c; 
      while ((c=in.read())!=-1) { 
           out.write(c); 
      } 
      in.close(); 
      out.close(); 
    } 
    con.setAutoCommit(false); 
    con.commit(); 
    } catch (Exception ex) { 
      ex.printStackTrace(); 
      throw ex; 
    } finally { 
     if (stmt != null) { 
      stmt.close(); 
    } 
    if (resultset != null) { 
      resultset.close(); 
    } 
    if (con!=null) { 
      con.close(); 
    } 
  } 
} 
  
下面的方法是从数据库中得到上传的文件的输入流,把输入流写到servlet流中,再从页面中获取,servlet就不写了。 
  /** 
   * 方法描述:得到数据库上传的文件数据 
   * 
   * 输入参数: 1:表名(String) 
   *          2:字段名(String) 
   *          3: Where条件(StringBuffer) 
   *          5: 输出流(ServletOutputStream) 
   * 
   * 输出参数:void 
   * 编写人:  */ 
  public static void getdownFile(String strTableName, 
                                         String strColumnName, 
                                         StringBuffer sbSQLWhere, 
                                         ServletOutputStream sos) throws Exception { 
    Connection con         = null; 
    PreparedStatement ps   = null; 
    ResultSet  resultset   = null; 
    try { 
      //得到数据库连接 
      con = DBConnector.getConnection(); 
      StringBuffer sbSQL = new StringBuffer(); 
      //构建查询语句 
      sbSQL.append(" SELECT " + strColumnName + " FROM " + strTableName); 
      sbSQL.append(sbSQLWhere); 
  
      System.out.println(" sql value is:"+sbSQLWhere.toString()); 
  
      ps = con.prepareStatement(sbSQL.toString()); 
      //执行查询 
      resultset  = ps.executeQuery(); 
      while (resultset.next()) { 
        //读取数据流 
        InputStream is = resultset.getBinaryStream(strColumnName); 
  
        byte[] buf = new byte[2048]; 
        while(is.read(buf)!=-1) { 
          //把数据流按块写到servlet的输出流中 
          sos.write(buf); 
        } 
  
      } 
    } catch (Exception ex) { 
      ex.printStackTrace(); 
      throw ex; 
    } finally { 
      if (ps != null) { 
        ps.close(); 
      } 
      if (resultset != null) { 
        resultset.close(); 
      } 
      if (con!=null) { 
        con.close(); 
      } 
    } 
  } 
图片的保存和文件的保存一样,如果不清楚的可以和我联系 
  
后记:   平时总忙着做项目,闲的时候也很懒,总想把自己实际中的一些问题和解决方法小结一下,但总没完成,这是第一次写,写的不好或不清楚的地方请包涵,下次改进,也希望大家多提意见,大家一起进步 !!!!!!!!!!! 
 
  |