博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
读写blob类型字段
阅读量:4048 次
发布时间:2019-05-25

本文共 4892 字,大约阅读时间需要 16 分钟。

主题:使用JAVA读取ORACLE BLOB字段实现上传下载

作者:蔡毅()
时间:2005-6-22

一 BLOB概述

大对象类型BLOB全称为Binary Large Objects,即二进制大对象。可以把BLOB区别为三种形式:声像数据、二进制数据和大文本数据。因此,最常见的应用就是存储图形、声音等对象,此外大二进制对象、OLE对象也可以通过BLOB类型存入数据库,如果文本对象过大,超出了文本类型的规定长度,则必须用BLOB字段进行存储。我们在经常使用的编程环境中并不能直接支持BLOB字段,因此需要调用相应的函数完成BLOB的使用。

二 实际Struts项目的处理流程

1 插入BLOB字段的流程

表示层:

上传使用struts的<html:file property="drawingFile"/>标签,提交给指定处理的Action,在ActionForm中使用struts自带的FormFile

来保存文件。

核心代码:
<html:form action="/DrawingInputMultiAction" enctype="multipart/form-data">
<html:file property="drawingFile"/>
....省略
</html:form>

控制层:

在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();
            conn.commit();
        } 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中调用这个私有方法,完成读取操作。

本文来自CSDN博客,转载请标明出处:

你可能感兴趣的文章
linux不同模块completion通信
查看>>
linux printf获得时间戳
查看>>
C语言位扩展
查看>>
linux irqdebug
查看>>
git 常用命令
查看>>
linux位操作API
查看>>
uboot.lds文件分析
查看>>
uboot start.s文件分析
查看>>
没有路由器的情况下,开发板,虚拟机Ubuntu,win10主机,三者也可以ping通
查看>>
本地服务方式搭建etcd集群
查看>>
安装k8s Master高可用集群
查看>>
忽略图片透明区域的事件(Flex)
查看>>
忽略图片透明区域的事件(Flex)
查看>>
AS3 Flex基础知识100条
查看>>
Flex动态获取flash资源库文件
查看>>
flex4 中创建自定义弹出窗口
查看>>
01Java基础语法-16. while循环结构
查看>>
01Java基础语法-18. 各种循环语句的区别和应用场景
查看>>
01Java基础语法-19. 循环跳转控制语句
查看>>
Django框架全面讲解 -- Form
查看>>