
使用java读取oracle blob字段.doc
8页使用使用 JAVAJAVA 读取读取 ORACLEORACLE BLOBBLOB 字段字段主题:使用 JAVA 读取 ORACLE BLOB 字段实现上传下载作者:蔡毅(caiyi0903@)时间:2005-6-22一 BLOB 概述大对象类型 BLOB 全称为 Binary Large Objects,即二进制大对象可以把 BLOB 区别为三种形式:声像数据、二进制数据和大文本数据因此,最常见的应用就是存储图形、声音等对象,此外大二进制对象、OLE 对象也可以通过 BLOB 类型存入数据库,如果文本对象过大,超出了文本类型的规定长度,则必须用 BLOB 字段进行存储我们在经常使用的编程环境中并不能直接支持 BLOB 字段,因此需要调用相应的函数完成 BLOB 的使用二 实际 Struts 项目的处理流程1 插入 BLOB 字段的流程表示层:上传使用 struts 的标签,提交给指定处理的 Action,在 ActionForm 中使用 struts 自带的FormFile来保存文件核心代码:....省略控制层:在 Action 中将传入的 ActionForm 中的文件字段赋给 VO 值对象,并调用业务代理类的上传方法。
核心代码://新增if(actionType.equals(“insert“)) {//得到文件类型int iFileType = this.getFileType(drawingInputForm.getFileExtendName());if(iFileType == 0) {//不支持文件类型this.addError(request, “drawing.errors.upload.UnSupportedFileType“);} else {DrawingVO objDrawingVO = new DrawingVO();//图纸基本属性objDrawingVO.setDrawingName(drawingInputForm.getDrawingName());...省略其他 set 方法//执行新增(上传)int iRt = objDrawingMan.insertDrawing(objDrawingVO);...省略}Facade 门面:通过业务代理类调用 DAO 中的上传方法,对客户端完全透明public int insertDrawing(DrawingVO drawingVO) throws ComtopModuleException {try {DrawingDAO drawingDAO = new DrawingDAO();return drawingDAO.insertDrawing(drawingVO);} catch(DrawingException ex) {throw new ComtopModuleException(“drawing.errors.insert“, ex);}}持久层:DAO 中实现和 ORACLE 数据库的底层交涉,完成真正的文件上传。
需要先插入一个空 BLOB 对象,然后 Update 这个空对象public int insertDrawing(DrawingVO drawingVO) throws DrawingException {PreparedStatement pstmt = null;Statement stmt = null;Connection conn = null;int iKey = 0;ResultSet rs = null;//定义 SQL 语句String strSQLInsert = null;String strSQLUpdate = null;try {conn = dataSource.getConnection();conn.setAutoCommit(false);//插入空 BLOB,empty_blob(),其中表中的 Content是 BLOC 类型字段strSQLInsert =“insert into PROD_DRAWING (DRAWING_ID, DRAWING_NAME, 省略...“ +“CONTENT)“ +“values (?, ?, 省略..., empty_blob())“;//得到待处理文件FormFile drawingFile = drawingVO.getDrawingFile();//插入普通字段pstmt = conn.prepareStatement(strSQLInsert);//得到主键iKey = Toolkit.getInstance().getNextKey(DrawingInfo.ID_STORE_KEY_DRAWING);pstmt.setInt(1, iKey);....省略其他 set 方法pstmt.executeUpdate();stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);strSQLUpdate =“SELECT CONTENT FROM PROD_DRAWING WHERE DRAWING_ID ='“ +iKey + “'“ + “ FOR UPDATE“;//读出记录以增加图片 Blob 字段rs = stmt.executeQuery(strSQLUpdate);if(rs.next()) {logger.debug(“开始写入 BLOB“);//这里不能用 oracle.sql.BLOB,会报 ClassCast异常weblogic.jdbc.vendor.oracle.OracleThinBlob blob = (weblogic.jdbc.vendor.oracle.OracleThinBlob)rs.getBlob(1);logger.debug(“得到输出流“);OutputStream outStream = blob.getBinaryOutputStream();InputStream fin = drawingFile.getInputStream();logger.debug(“开始分配缓存“);byte[] b = new byte[blob.getBufferSize()];int len = 0;while((len = fin.read(b)) != -1) {logger.debug(“正在写入 BLOB 流“);outStream.write(b, 0, len);}logger.debug(“关闭所有流“);fin.close();outStream.flush();outStream.close();}rs.close();mit();} catch(Exception ex) {...省略}finally {DBUtil.destroyDB(rs, pstmt, conn);}return iKey;}2 读取 BLOB 字段的流程从数据库中读出 BLOB 数据没有上述由于连接池的不同带来的差异,程序流程同插入 BLOB 字段,但是读 BLOB 就不用那么复杂了,只需要 J2SE 的标准类 java.sql.Blob 就可以取得输出流。
DAO 中的核心代码:public DrawingVO readDrawing(int drawingId) throws DrawingException {PreparedStatement pstmt = null;Connection conn = null;DrawingVO objDrawingVO = null;ResultSet rs = null;//定义 SQL 语句String strSQL = “SELECT * FROM PROD_DRAWING WHERE DRAWING_ID=?“;try {conn = dataSource.getConnection();pstmt = conn.prepareStatement(strSQL);//设置参数pstmt.setInt(1, drawingId);//执行查询rs = pstmt.executeQuery();while(rs.next()) {objDrawingVO = new DrawingVO();objDrawingVO.setDrawingId(rs.getInt(“DRAWING_ID“));objDrawingVO.setDrawingName(rs.getString(“DRAWING_NAME“));...省略其他 set 方法//set BLOB 到 VO 中objDrawingVO.setContent(rs.getBlob(“CONTENT“));}} catch(Exception ex) {...省略}finally {DBUtil.destroyDB(rs, pstmt, conn);}return objDrawingVO;}这样,传到 Action 中 VO 对象就包含这个 BLOB 对象了,然后需要在Action 中对该对象转为输入流,可以选择文件输出流或 Servlet 输出流,根据具体情况定,这里选择文件输出流。
核心代码:private String getBlobToFile(Blob blob, DrawingVO objDrawingVO) throws Exception {InputStream ins = blob.getBinaryStream();//用文件模拟输出流String strFileName = objDrawingVO.getDrawingName() + “.“ +objDrawingVO.getFileExtendName();String strRootFilePath = this.getServlet().getServletContext().getRealPath(““);String strFilePath = “/temp/“ + strFileName;String contextFilePath = strRootFilePath + strFilePath;//定义文件对象File file = new File(this.getServlet().getServletContext().getRealPath(““) + “/temp“);if(!file.exists()) {file.mkdir();}//定义输出流OutputStream fout = new FileOutputStream(contextFilePath, true);//下面将 BLOB 数据写入文件byte[] b = new byte[1024];int len = 0;while((len = ins.read(b)) != -1) {fout.write(b, 0, len);}//依次关闭fout.close();ins.close();return strFilePath;}最后,在 Action 中调用这个私有方法,完成读取操作。
