在处理维基百科数据的时候从数据库提取text需要读取BLOB数据,一切简单问题规模变大之后都会变得棘手。。
在多次读取BLOB时我建议使用第一种方法,同时要记着把第11行的outStream设null及时收回,否则就等着Heap Space喊饿吧~第二种方法不推荐是因为String result =
new
String(b,
"utf-8"
);会经常因为string转化时数组越界挂掉,当然真正原因还是需要从源码分析。。
今天写了个SQL查数据库,需要根据id分组,然后将同一分组中某几列的值都平铺开来,网络上查了下,MySQL中的 GROUP_CONCAT 函数,还是很好用的,SQL 大致写成如下:
1
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,代码如下
第一种方法:
01
public
String getBlob(String SQL){
02
Connection conn =
null
;
03
PreparedStatement stmt =
null
;
06
conn = dataSource.getConnection();
07
stmt = conn.prepareStatement(SQL);
08
rs = stmt.executeQuery();
10
InputStream in = rs.getBinaryStream(
1
);
11
ByteArrayOutputStream outStream =
new
ByteArrayOutputStream();
12
byte
[] data =
new
byte
[
4096
];
14
while
((count = in.read(data,
0
,
4096
)) != -
1
)
15
outStream.write(data,
0
, count);
18
String result =
new
String(outStream.toByteArray(),
"utf-8"
);
19
}
catch
(SQLException sqle) {
20
log.warn(
"Exception XXX"
, sqle);
第二种方法:
01
public
String getBlob(String SQL){
02
Connection conn =
null
;
03
PreparedStatement stmt =
null
;
06
conn = dataSource.getConnection();
07
stmt = conn.prepareStatement(SQL);
08
rs = stmt.executeQuery();
10
Blob bb = rs.getBlob(i);
11
byte
[] b = bb.getBytes(
1
, (
int
)bb.length());
13
String result =
new
String(b,
"utf-8"
);
14
}
catch
(SQLException sqle) {
15
log.warn(
"Exception XXX"
, sqle);
这里看第二种方法要简单点,但是第一种貌似是用来直接将结果写入文件中,因为我这里需要转换成String,所以偏第二种。
最后我想在 DBUtils里面读取的时候就直接帮我转换的,研究了一下源代码后,貌似这么改可以做到,加一层判断,若结果类型为BLOB 则用上述读法。若不是还是按原来的逻辑走,修改的是以修改 org.apache.commons.dbutils. BasicRowProcessor 中的将结果封装诚Map的方法为例( RowProcessor为用于处理数据封装的,还有封装其他 数据结构的方法你也可以根据需要改 ),改的不好,见笑了:
01
public
Map<String, Object> toMap(ResultSet rs)
throws
SQLException {
02
Map<String, Object> result =
new
CaseInsensitiveHashMap();
03
ResultSetMetaData rsmd = rs.getMetaData();
04
int
cols = rsmd.getColumnCount();
06
for
(
int
i =
1
; i <= cols; i++) {
08
if
(rsmd.getColumnTypeName(i).equals(
"BLOB"
)){
09
Blob bb = rs.getBlob(i);
10
byte
[] b = bb.getBytes(
1
, (
int
)bb.length());
14
result.put(rsmd.getColumnName(i),
new
String(b,
"utf-8"
));
15
}
catch
(UnsupportedEncodingException e) {
21
result.put(rsmd.getColumnName(i), rs.getObject(i));
原创博客,转载请注明 http://my.oschina.net/BreathL/blog/63359