JDBC讀取MySQL的BLOB類型

openkk 12年前發布 | 56K 次閱讀 MySQL 數據庫服務器

     今天寫了個SQL查數據庫,需要根據id分組,然后將同一分組中某幾列的值都平鋪開來,網絡上查了下,MySQL中的 GROUP_CONCAT 函數,還是很好用的,SQL 大致寫成如下:

select `id` , GROUP_CONCAT(concat(`key`,':',`value`) ORDER BY `key`  SEPARATOR ",") as prefs from `table_name` GROUP BY `id`

     效果還算不錯,但是在Java程序中查詢這條SQL時,卻出現了一些小意外,分組排列的字段顯示不出來,我當時使DBUtils 查的,用MapListHandler 來讀出的該字段,讀出來全是亂碼, 于是跟到源碼里,調了半天不知道問題,后來同事提示才發現,由于同一組中,個數太多,導致這些值產生的字符串很長,于是MySQL會自動把這列的結果類型轉換成BLOB,這種類型讀取的方式很特別,若用JDBC中 getObject(int index)方法讀取的話,就會是亂碼(DBUtils這里就是用的JDBC中的  getObject(int index) 來讀取數據)。

     讀取數據庫中BLOB數據類型的方法,我在網上找了一下,找到兩種,根據自身情況也實現了一下,我需要將BLOB類型 轉換成String,代碼如下

第一種方法:

public String getBlob(String SQL){
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
            try {
                conn = dataSource.getConnection();//c3p0連接池
                stmt = conn.prepareStatement(SQL);//SQL: select info from table1 (其中info字段是blob類型) 
                rs = stmt.executeQuery();

                InputStream in = rs.getBinaryStream(1);
                ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                byte[] data = new byte[4096];
                int count = -1;
                while((count = in.read(data,0,4096)) != -1)
                    outStream.write(data, 0, count);

                data = null;
                String result = new String(outStream.toByteArray(),"utf-8");
            } catch (SQLException sqle) {
                log.warn("Exception XXX", sqle);
            }finally{
                conn.close();
                stmt.close();
            }
    }

第二種方法:

public String getBlob(String SQL){
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
            try {
                conn = dataSource.getConnection();//c3p0連接池
                stmt = conn.prepareStatement(SQL);//SQL: select info from table1 (其中info字段是blob類型) 
                rs = stmt.executeQuery();

                Blob bb = rs.getBlob(i);
                byte[] b = bb.getBytes(0, (int)bb.length());

                String result = new String(b,"utf-8");
            } catch (SQLException sqle) {
                log.warn("Exception XXX", sqle);
            }finally{
                conn.close();
                stmt.close();
            }
    }

     這里看第二種方法要簡單點,但是第一種貌似是用來直接將結果寫入文件中,因為我這里需要轉換成String,所以偏第二種。

     最后我想在 DBUtils里面讀取的時候就直接幫我轉換的,研究了一下源代碼后,貌似這么改可以做到,加一層判斷,若結果類型為BLOB 則用上述讀法。若不是還是按原來的邏輯走,修改的是以修改 org.apache.commons.dbutils.BasicRowProcessor 中的將結果封裝誠Map的方法為例(RowProcessor為用于處理數據封裝的,還有封裝其他數據結構的方法你也可以根據需要改),改的不好,見笑了:

public Map<String, Object> toMap(ResultSet rs) throws SQLException {
        Map<String, Object> result = new CaseInsensitiveHashMap();
        ResultSetMetaData rsmd = rs.getMetaData();
        int cols = rsmd.getColumnCount();

        for (int i = 1; i <= cols; i++) {
            //通過ResultSetMetaData類,可判斷該列數據類型
            if(rsmd.getColumnTypeName(i).equals("BLOB")){
                Blob bb = rs.getBlob(i);
                byte[] b = bb.getBytes(0, (int)bb.length());

                try {
                    //將結果放到Map中
                    result.put(rsmd.getColumnName(i), new String(b,"utf-8"));
                } catch (UnsupportedEncodingException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } 
            }else{
                //不是則按原來邏輯運算
                result.put(rsmd.getColumnName(i), rs.getObject(i));
            }
        }

        return result;
    }

轉載 http://my.oschina.net/BreathL/blog/63359

 本文由用戶 openkk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!