mybatis的BLOB儲存與讀取

來源:互聯網
上載者:User
簡單介紹一下背景環境,web開發避免不了照片附件之類的東東,原先是存到硬碟的檔案下,儲存讀取都比較方便。現在公司弄了個硬體負載平衡,6台伺服器,當使用者登入的時候會隨機分配到其中的一台機器上,6台機器安裝的相同的server,session不共用。訪問的同一個oracle11.2g,這樣的話,原先的附件就可能不好使了,必須保證6台機器共用檔案,想想直接放到資料庫裡吧,將來再做個本機快取之類的。ok背景就到這裡。

第一步,沒做過大欄位的存取,網上查資料,N多資料,總體來說有用的不多,但也要硬著頭皮找,開始看mybatis和資料庫的欄位對照表,bytes[]對應的是blob欄位,於是在pojo類中的content設定類型為byte[],mapper.xml中設定了resultMap,欄位content設定<result property="content" column="content" jdbcType="BLOB"  typeHandler="com.ibatis.sqlmap.engine.type.BlobTypeHandlerCallback"/>

結果總是報”ora-01461“的錯誤,網上查詢了一下,基本意思就是超出長度了。但是明明是大欄位,圖片大小也就是70k,不可能超出長度

1)人為把byte定義一個長度 byte[0] = 1,繼續插入資料庫,成功。但是這不符合我的需求,這哪是大欄位

2)繼續網上搜尋,說是用byte[]這種形式傳的話,1000-2000之間的位元組會報‘ora-01461’的錯誤,網上有給出編寫oracleLobHandler的做法,不過他用的是hibernate,大欄位是clob,處於懶人目的直接忽略

3)終於找到一篇有用的文章,我的大體裡程也是按照他的方法來的http://www.360doc.com/content/06/0913/13/6272_206215.shtml,總結一下裡面提到的

1》pojo類中不能使用byte[],也不能使用BLOB,這兩種鄙人也都用過確實無效,使用Object

2》mapper.mxl中的resultMap把typeHandler去掉,我也懷疑內建的這個類型處理器不是很好使,不能將blob轉換成byte[]等,這裡建議有時間的同學可以自己寫一個再試試,感覺應該是能成功的,不然換成Object強制類型轉換估計也沒戲。

3》oracle存大資料的時候,要先插入一個empty_blob()預留位置,佔到blob欄位,其次在查詢出來這個大欄位用流的方式寫入。

4》在進行流讀取的時候,發現blob.getBinaryOutputStream();已經過時了,於是改成了推薦的blob.setBinaryStream(0);發現總是提示"無效的參數...",經查看發現是oracle驅動的問題,當時的環境是oracle11.2g+ojdbc6.jar+jdk1.6,查看setBinaryStream這個api說適用於jdbc3.0,按理說都應該滿足了,經替換髮現,ojdbc6,ojdbc5都出問題,換成支援1.4jdk的ojdbc14.jar不會出問題,但是驅動越高,效率越高,bug越少,所以一直用的過時的方法。

下面把我儲存和讀取的主要代碼附上:

pojo類:

[html] view plaincopy在CODE上查看代碼片派生到My Code片

    public class Attachment {  
        private String id;  
        private String group;//分類的id,包括訊息附件、照片等  
        private String name;  
        private String type;  
        private String size;  
        private String author;  
        private Object content;  
        public Object getContent() {  
            return content;  
        }  
        public void setContent(Object content) {  
            this.content = content;  
        }  
        public String getId() {  
            return id;  
        }  
        public void setId(String id) {  
            this.id = id;  
        }  
        public String getGroup() {  
            return group;  
        }  
        public void setGroup(String group) {  
            this.group = group;  
        }  
        public String getName() {  
            return name;  
        }  
        public void setName(String name) {  
            this.name = name;  
        }  
        public String getType() {  
            return type;  
        }  
        public void setType(String type) {  
            this.type = type;  
        }  
        public String getSize() {  
            return size;  
        }  
        public void setSize(String size) {  
            this.size = size;  
        }  
        public String getAuthor() {  
            return author;  
        }  
        public void setAuthor(String author) {  
            this.author = author;  
        }  
          
    }  

[html] view plaincopy在CODE上查看代碼片派生到My Code片

    map.xml中的resultMap和sql:  

[java] view plaincopy在CODE上查看代碼片派生到My Code片

    <resultMap id="attachmentResultMap" type="attachment">     
        <result property="id" column="id"/>     
        <result property="group" column="groupId"/>  
        <result property="name" column="fileName" />  
        <result property="type" column="fileType" />  
        <result property="size" column="fileSize" />  
        <result property="author" column="author" />  
        <result property="content" column="content" jdbcType="BLOB" />  
    </resultMap>  
    <insert id="insertAttachment" parameterType="attachment">  
        insert into bop_attachment (id,filename,filetype,filesize,author,content,groupid)  
        values(#{id},#{name},#{type},#{size},#{author},empty_blob(),#{group})  
    </insert>  

service層儲存的主要方法:

[java] view plaincopy在CODE上查看代碼片派生到My Code片

    @Override  
    public void insertAttachment(Attachment attachment,File file)  
            throws AttachmentServiceException {  
        attachmentDao.insertAttachment(attachment);  
        Attachment att = attachmentDao.queryAttachmentById(attachment.getId());  
        BLOB content = (BLOB)att.getContent();  
        FileInputStream fis = null;  
        OutputStream ops = null;  
        try {  
            ops = content.getBinaryOutputStream();//暫時使用這個廢棄的方法  
            //ops = content.setBinaryStream(0);//ojdbc14支援,ojdbc6,5都不支援  
            fis = new FileInputStream(file);  
            byte[] data = null;  
            data = FileCopyUtils.copyToByteArray(fis);  
            ops.write(data);  
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                if(fis!=null){  
                    fis.close();  
                }  
                if(ops!=null){  
                    ops.close();  
                }  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  



用於圖片展示的servlet層:

[java] view plaincopy在CODE上查看代碼片派生到My Code片

    AttachmentService as = (AttachmentService) SpringUtils.getContext().getBean("AttachmentService");  
    Attachment attachment = null;  
    try {  
        attachment = as.queryAttachmentById(attachmentId);  
    } catch (AttachmentServiceException ae) {  
        logger.error(ae);  
        throw new ServletException(ae);  
    }  
    //String realPath = rootDir + attachment.getName();  
    response.setContentType(attachment.getType());  
    response.setContentLength(Integer.parseInt(attachment.getSize()));  
    response.setHeader("Content-Disposition", "attachment; filename="  
            + java.net.URLEncoder.encode(attachment.getName(), "UTF-8")  
            + ';');  
    InputStream in = null;  
    BLOB content = (BLOB)attachment.getContent();  
    try {  
        in=content.getBinaryStream();  
    } catch (SQLException e) {  
        e.printStackTrace();  
    }  
    BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());  
    int n;  
    while ((n=in.read())!=-1){  
        bos.write(n);  
    }  
    bos.flush();  
    bos.close();  
    in.close();  


轉載自:http://blog.csdn.net/bluesky5219/article/details/36427789

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.