BLOB
BLOB全称为二进制大型对象(Binary Large Object)。它用于存储数据库中的大型二进制对象。可存储的最大大小为4G字节,通常像图片、文件、音乐等信息就用BLOB字段来存储。
CLOB
CLOB全称为字符大型对象(Character Large Object)。它与LONG数据类型类似,只不过CLOB用于存储数据库中的大型单字节字符数据块,不支持宽度不等的字符集。可存储的最大大小为4G字节,文章或者是较长的文字,就用CLOB存储,这样对以后的查询更新存储等操作都提供很大的方便。
Java操作BLOB和CLOB
insert语句不支持blob字段的超长16进制字符串,执行sql会提示过长(较短可以)。
一、mysql数据库
写字段
存--手动执行sql语句,借助load_file()函数
# /absPath 为文件所在路径
insert into image_source(id, column_blob) values ('123', load_file("/absPath"));
存--使用preparedStatement
public static void insertBlobValue(File file){
PreparedStatement ps = connection.prepareStatement("insert into image_source (id, column_blob) values (?, ?)");
ps.setInt(1, 123);
//输入流
ps.setBlob(2, file.getInputStream(), file.getSize());
ps.execute();
}
存--使用jdbcTemplate
//借助LobHandler
final LobHandler lobHandler = new DefaultLobHandler();
jdbcTemplate.execute(modelSql, new AbstractLobCreatingPreparedStatementCallback(lobHandler) {
@Override
protected void setValues(PreparedStatement preparedStatement, LobCreator lobCreator) throws SQLException, DataAccessException {
lobCreator.setClobAsString(preparedStatement, 3, "yourClobContent");
}
});
LobCreator提供了多个接口来简化大字段的写入:对于BLOB,内容来源可以是InputStream、byte[];对于CLOB,内容来源可以是InputStream(自行确保都是ascii字符)、Reader、String。
读字段
同下Oracle方法。
二、oracle数据库
同mysql,blob无法直接insert,需要借助存储过程,CallableStatement,PreparedStatement,或JdbcTemplate。
写字段
一、使用存储过程, 脚本内容如下,hex串过长省略。
DECLARE
v_blob BLOB;
BEGIN
v_blob :=HEXTORAW('7B227265736F75.....');
INSERT INTO "AML_PLATFORM"."ACT_GE_BYTEARRAY"("ID_", "REV_", "NAME_", "DEPLOYMENT_ID_", "BYTES_", "GENERATED_")
values ('900101', '1', 'risk', '', v_blob, '1');
end;
可以直接执行该脚本入库数据。
二、使用CallableStatement获取脚本内容执行
//该方式较麻烦,愿意使用的可以网上搜下
三、java代码执行脚本
InputStream inputStream = file.getInputStream();
ScriptRunner runner = new ScriptRunner(jdbcTemplate.getDataSource().getConnection());
runner.setAutoCommit(true);
runner.setStopOnError(true);
runner.setEscapeProcessing(false);
runner.setSendFullScript(true);
runner.runScript(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
四、PreparedStatement同mysql
五、JdbcTemplate
LobHandler lobHandler = new DefaultLobHandler(); // reusable object
jdbcTemplate.execute(
"INSERT INTO imagedb (image_name, content, description) VALUES (?, ?, ?)",
new AbstractLobCreatingPreparedStatementCallback(lobHandler) {
protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException {
ps.setString(1, name);
lobCreator.setBlobAsBinaryStream(ps, 2, contentStream, contentLength);
//lobCreator.setClobAsString(ps, 3, description);
}
}
);
读字段
mybatis等框架也封装了特殊字段的处理方法,但是使用起来比较麻烦,这里仅写jdbcTemplate示例
//我的方法
String modelSql = "SELECT * FROM ACT_GE_BYTEARRAY WHERE ID_ in (SELECT EDITOR_SOURCE_VALUE_ID_ FROM ACT_RE_MODEL where ID_= ?)";
List<Map<String, String>> query = jdbcTemplate.query(modelSql, new Object[]{flowId}, (resultSet, i) -> {
final LobHandler lobHandler = new DefaultLobHandler();
InputStream binaryStream = lobHandler.getBlobAsBinaryStream(resultSet, 5);
IOUtils.toByteArray(binaryStream);
byte[] blobAsBytes = lobHandler.getBlobAsBytes(resultSet, 5);
String bytes = new String(blobAsBytes);
HashMap<String, String> map = new HashMap<>(6);
map.put("ID_", resultSet.getString(1));
map.put("REV_", resultSet.getString(2));
map.put("NAME_", resultSet.getString(3));
map.put("DEPLOYMENT_ID_", resultSet.getString(4));
map.put("BYTES_", bytes);
map.put("GENERATED_", resultSet.getString(6));
return map;
});
//取出后为16进制字符串
//网上方法
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); // reusable object
final LobHandler lobHandler = new DefaultLobHandler(); // reusable object
jdbcTemplate.query(
"SELECT content FROM imagedb WHERE image_name=?", new Object[] {name},
new AbstractLobStreamingResultSetExtractor() {
public void streamData(ResultSet rs) throws SQLException, IOException {
//业务处理
}
}
);
两种仅区别于query的实现,实际上都是借助于spring封装的Lobhandler。
CLOB
clob不区分库
读, 使用ResultSet或LobHandler
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); // reusable object
final LobHandler lobHandler = new DefaultLobHandler(); // reusable object
jdbcTemplate.query(
"SELECT content FROM imagedb WHERE image_name=?", new Object[] {name},
new AbstractLobStreamingResultSetExtractor() {
public void streamData(ResultSet rs) throws SQLException, IOException {
resultSet.getAsciiStream("columnIndex"/"clolumnName");
resultSet.getCharacterStream("columnIndex"/"clolumnName");
lobHandler.getClobAsAsciiStream("columnIndex"/"clolumnName");
lobHandler.getClobAsCharacterStream("columnIndex"/"clolumnName");
lobHandler.getClobAsString("columnIndex"/"clolumnName");
//业务处理
}
}
);
写,使用PreparedStatement
PreparedStatement ps = connection.prepareStatement("insert into image_source (id, column_blob, column_clob) values (?, ?, ?)");
ps.setInt(1, 123);
ps.setBlob(2, file.getInputStream(), file.getSize());
ps.setClob(3, new InputStreamReader(file.getInputStream()) , file.getSize());
ps.execute();
使用jdbcTemplate
jdbcTemplate.execute(modelSql, new AbstractLobCreatingPreparedStatementCallback(lobHandler) {
@Override
protected void setValues(PreparedStatement preparedStatement, LobCreator lobCreator) throws SQLException, DataAccessException {
lobCreator.setClobAsString(preparedStatement, 3, "yourClobContent");
lobCreator.setClobAsAsciiStream(参数);
lobCreator.setClobAsCharacterStream(参数);
}
});