LobHandler和LobCreator
处理 BLOB 和 CLOB 对象
您可以在数据库中存储图像,其他二进制数据和大块文本。这些大对象称为二进制数据的 BLOB(二进制大型对象),而字符数据称为 CLOB(字符大型对象)。在 Spring 中,可以直接使用JdbcTemplate
来处理这些大对象,也可以使用 RDBMS Objects 和SimpleJdbc
类提供的更高抽象来处理这些大对象。所有这些方法都将LobHandler
接口的实现用于 LOB(大对象)数据的实际 Management。 LobHandler
通过getLobCreator
方法提供对LobCreator
类的访问,该方法用于创建要插入的新 LOB 对象。
LobCreator
和LobHandler
为 LOBImporting 和输出提供以下支持:
- BLOB
byte[]
:getBlobAsBytes
和setBlobAsBytes
InputStream
:getBlobAsBinaryStream
和setBlobAsBinaryStream
- CLOB
String
:getClobAsString
和setClobAsString
InputStream
:getClobAsAsciiStream
和setClobAsAsciiStream
Reader
:getClobAsCharacterStream
和setClobAsCharacterStream
下一个示例显示了如何创建和插入 BLOB。稍后,我们展示如何从数据库中读取它。
本示例使用JdbcTemplate
和AbstractLobCreatingPreparedStatementCallback
的实现。它实现了一种方法setValues
。此方法提供LobCreator
,我们可以用来设置 SQL 插入语句中 LOB 列的值。
对于此示例,我们假设存在一个变量lobHandler
,该变量已设置为DefaultLobHandler
的实例。通常,您可以通过依赖注入来设置此值。
以下示例显示如何创建和插入 BLOB:
final File blobIn = new File("spring2004.jpg");
final InputStream blobIs = new FileInputStream(blobIn);
final File clobIn = new File("large.txt");
final InputStream clobIs = new FileInputStream(clobIn);
final InputStreamReader clobReader = new InputStreamReader(clobIs);
jdbcTemplate.execute(
"INSERT INTO lob_table (id, a_clob, a_blob) VALUES (?, ?, ?)",
new AbstractLobCreatingPreparedStatementCallback(lobHandler) { (1)
protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException {
ps.setLong(1, 1L);
lobCreator.setClobAsCharacterStream(ps, 2, clobReader, (int)clobIn.length()); (2)
lobCreator.setBlobAsBinaryStream(ps, 3, blobIs, (int)blobIn.length()); (3)
}
}
);
blobIs.close();
clobReader.close();
- (1) 传递
lobHandler
(在此示例中)为普通DefaultLobHandler
。 - (2) 使用方法
setClobAsCharacterStream
传递 CLOB 的内容。 - (3) 使用方法
setBlobAsBinaryStream
传入 BLOB 的内容。
如果在从DefaultLobHandler.getLobCreator()
返回的LobCreator
上调用setBlobAsBinaryStream
,setClobAsAsciiStream
或setClobAsCharacterStream
方法,则可以选择为contentLength
参数指定负值。如果指定的内容长度为负数,则DefaultLobHandler
使用不带 length 参数的 set-stream 方法的 JDBC 4.0 变体。否则,它将指定的长度传递给驱动程序。
现在是时候从数据库中读取 LOB 数据了。同样,您使用具有相同实例变量lobHandler
的JdbcTemplate
和对DefaultLobHandler
的引用。以下示例显示了如何执行此操作:
List<Map<String, Object>> l = jdbcTemplate.query("select id, a_clob, a_blob from lob_table",
new RowMapper<Map<String, Object>>() {
public Map<String, Object> mapRow(ResultSet rs, int i) throws SQLException {
Map<String, Object> results = new HashMap<String, Object>();
String clobText = lobHandler.getClobAsString(rs, "a_clob"); (1)
results.put("CLOB", clobText);
byte[] blobBytes = lobHandler.getBlobAsBytes(rs, "a_blob"); (2)
results.put("BLOB", blobBytes);
return results;
}
});
-
(1) 使用方法
getClobAsString
检索 CLOB 的内容。 -
(2) 使用方法
getBlobAsBytes
检索 BLOB 的内容。
示例代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class SpringLobTest {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private LobHandler lobHandler;
@Test
public void testWrite(){
try {
//准备images的字节数组
Resource resource = new FileSystemResource("C:\\Users\\zhy\\Desktop\\6.jpg");
byte[] images = FileCopyUtils.copyToByteArray(resource.getFile());
//准备description
String description = "BLOB (binary large object),二进制大对象,是一个可以存储二进制文件的容器。\n" +
"在计算机中,BLOB常常是数据库中用来存储二进制文件的字段类型。\n" +
"BLOB是一个大文件,典型的BLOB是一张图片或一个声音文件,\n" +
"由于它们的尺寸,必须使用特殊的方式来处理(例如:上传、下载或者存放到一个数据库)。\n" +
"根据Eric Raymond的说法,处理BLOB的主要思想就是让文件处理器(如数据库管理器)不去理会文件是什么,\n" +
"而是关心如何去处理它。但也有专家强调,这种处理大数据对象的方法是把双刃剑,\n" +
"它有可能引发一些问题,如存储的二进制文件过大,会使数据库的性能下降。\n" +
"在数据库中存放体积较大的多媒体对象就是应用程序处理BLOB的典型例子。";
//1.创建Userinfo
Userinfo userinfo = new Userinfo();
userinfo.setImages(images);
userinfo.setDescription(description);
jdbcTemplate.execute("insert into userinfo(images,description)values(?,?)", new AbstractLobCreatingPreparedStatementCallback(lobHandler) {
@Override
protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException, DataAccessException {
lobCreator.setBlobAsBytes(ps, 1, userinfo.getImages());
lobCreator.setClobAsString(ps, 2, userinfo.getDescription());
}
});
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void testRead(){
Userinfo userinfo = jdbcTemplate.query("select * from userinfo where id = ?", new ResultSetExtractor<Userinfo>() {
@Override
public Userinfo extractData(ResultSet rs) throws SQLException, DataAccessException {
Userinfo userinfo1 = null;
if(rs.next()){
userinfo1 = new Userinfo();
userinfo1.setId(rs.getInt("id"));
userinfo1.setImages(lobHandler.getBlobAsBytes(rs,"images"));
userinfo1.setDescription(lobHandler.getClobAsString(rs,"description"));
}
return userinfo1;
}
}, 1);
System.out.println(userinfo);
}
}