风之力

BlogJava 首页 新随笔 联系 聚合 管理
  19 Posts :: 2 Stories :: 18 Comments :: 0 Trackbacks

做了个简单的通告管理,在本机测试时数据量比较小。最开始用的时varchar2到2000,之后用hibernate中的text类型,对应数据库中的Clob类型。当数据量小于4000时,可以直接使用setObject()插入数据库。当数据量大于4000时。报错:socket write error。
查找了一些资料,说当数据量超过4000时,应该使用流方式操作。看到头昏昏,烦都烦死了......
最后发现Spring封装了对lob数据的操作,可以直接使用jdbcTemple操作lob数据。
当使用MySql、MSSQL、Oracle 10g时,使用DefaultLobHandler;使用Oracle 9i时使用OracleLobHandler。
示例代码:【转值javaWorld】

 1         final File binaryFile = new File("c:\\workspace\\wish.jpg" );
 2         final File txtFile = new File("c:\\workspace\\test.txt"
);
 3 
       
 4         final InputStream is = new
 FileInputStream(binaryFile);
 5         final Reader reader = new
 FileReader(txtFile);
 6 
       
 7         JdbcTemplate jdbcTemplate = new
 JdbcTemplate(dataSource);
 8 
       
 9         final LobHandler lobHandler = new
 DefaultLobHandler();
10 
       
11         jdbcTemplate.execute("INSERT INTO test (txt, image) VALUES(?, ?)"
,
12                      new
 AbstractLobCreatingPreparedStatementCallback(lobHandler) {
13                         protected void
 setValues(PreparedStatement pstmt, LobCreator lobCreator)
14                                                            throws
 SQLException, DataAccessException {
15                             lobCreator.setClobAsCharacterStream(pstmt, 1, reader, (int
) txtFile.length());
16                             lobCreator.setBlobAsBinaryStream(pstmt, 2, is, (int
) binaryFile.length());
17 
                        }
18 
                     });
19 
       
20 
        reader.close();
21 
        is.close();
22 

读取代码:

 1         final Writer writer = new FileWriter("c:\\workspace\\test_bak.txt" );
 2         final OutputStream os = new FileOutputStream(new File("c:\\workspace\\wish_bak.jpg"
));
 3 
       
 4         jdbcTemplate.query("SELECT txt,image FROM test WHERE id = ?"
,
 5                 new Object[] {new Integer(1
)},
 6                 new
 AbstractLobStreamingResultSetExtractor() {
 7                     protected void streamData(ResultSet rs) throws
 SQLException, IOException, DataAccessException {
 8                         FileCopyUtils.copy(lobHandler.getClobAsCharacterStream(rs, 1
), writer);
 9                         FileCopyUtils.copy(lobHandler.getBlobAsBinaryStream(rs, 2
), os);
10 
                    }
11 
                 });
12 
        writer.close();
13 
        os.close();
14 

15 
备注1:OracleLobHandler要求注入CommonsDbcpNativeJdbcExtractor,否则报错:要求使用OracleConnection,不可以使用Dbcp连接池。
1      < bean id = " lobHandler "   class = " org.springframework.jdbc.support.lob.OracleLobHandler " >
2      < property name = " nativeJdbcExtractor " >
3         < bean  class = " org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor " />
4     </ property >
5     </ bean >
备注2:Oracle驱动版本很多,要求使用正确的驱动。当驱动版本错误时,报错:无法释放LobHandler;无法关闭Writer;无法从套接字读取更多的信息。执行插入操作,但是Clob类型数据为空。
posted on 2006-11-08 16:20 风之力 阅读(5549) 评论(4)  编辑  收藏 所属分类: java

Feedback

# re: spring下lob数据处理【原创】 2008-08-01 15:29 gyhgc
同时读取多个图片文件呢,如何处理呢?
String name = rs.getString(2);
final OutputStream os = new FileOutputStream(new File(path+name));
FileCopyUtils.copy(lobHandler.getBlobAsBinaryStream(rs, 1), os);
list.add(name);
os.close();
while(rs.next()){
name = rs.getString(2);
final OutputStream os1 = new FileOutputStream(new File(path+name));
FileCopyUtils.copy(lobHandler.getBlobAsBinaryStream(rs, 1), os1);
list.add(name);
os1.close();

}
直接写while(rs.next()) 第一个图片取不到,如何写才正确呢?  回复  更多评论
  

# re: spring下lob数据处理【原创】 2008-08-04 10:14 风之力
@gyhgc
不是很明白你的意思,操作应该都是一样的
你是指不要上面那段,直接写
while(rs.next()){
name = rs.getString(2);
final OutputStream os1 = new FileOutputStream(new File(path+name));
FileCopyUtils.copy(lobHandler.getBlobAsBinaryStream(rs, 1), os1);
list.add(name);
os1.close();
}
取不到第一张图片?
  回复  更多评论
  

# re: spring下lob数据处理【原创】 2008-08-04 11:10 gyhgc
是的,就是rs的指针已经指向了第一行的位置。rs.next()只能从第二行开始读取了。  回复  更多评论
  

# re: spring下lob数据处理【原创】 2008-08-05 08:57 风之力
@gyhgc
AbstractLobStreamingResultSetExtractor的
public final Object extractData(ResultSet rs) throws SQLException, DataAccessException {
if (!rs.next()) {
handleNoRowFound();
}
else {
try {
streamData(rs);
if (rs.next()) {
handleMultipleRowsFound();
}
}
catch (IOException ex) {
throw new LobRetrievalFailureException("Couldn't stream LOB content", ex);
}
}
return null;
}
是先做了一次rs.next()的,所以rs的指针是指到第一行的
你可以do{}while(rs.next())的嘛......
  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: