JDBC讀取MySQL的BLOB類型

     今天寫了個SQL查數據庫,須要根據id分組,而後將同一分組中某幾列的值都平鋪開來,網絡上查了下,MySQL中的 GROUP_CONCAT 函數,仍是很好用的,SQL 大體寫成以下:java

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) 來讀取數據)。sql

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

第一種方法:apache

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(1, (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(1, (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/63359spa

相關文章
相關標籤/搜索