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" > </ 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文本对象* sbSQL* * 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);bResult.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字段中* strTableName 对应的表名称* 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就不写了。