LobHandler和LobCreator

处理 BLOB 和 CLOB 对象

您可以在数据库中存储图像,其他二进制数据和大块文本。这些大对象称为二进制数据的 BLOB(二进制大型对象),而字符数据称为 CLOB(字符大型对象)。在 Spring 中,可以直接使用JdbcTemplate来处理这些大对象,也可以使用 RDBMS Objects 和SimpleJdbc类提供的更高抽象来处理这些大对象。所有这些方法都将LobHandler接口的实现用于 LOB(大对象)数据的实际 Management。 LobHandler通过getLobCreator方法提供对LobCreator类的访问,该方法用于创建要插入的新 LOB 对象。

LobCreatorLobHandler为 LOBImporting 和输出提供以下支持:

  • BLOB
  • byte[]getBlobAsBytessetBlobAsBytes
    • InputStreamgetBlobAsBinaryStreamsetBlobAsBinaryStream
  • CLOB
  • StringgetClobAsStringsetClobAsString
    • InputStreamgetClobAsAsciiStreamsetClobAsAsciiStream
    • ReadergetClobAsCharacterStreamsetClobAsCharacterStream

下一个示例显示了如何创建和插入 BLOB。稍后,我们展示如何从数据库中读取它。

本示例使用JdbcTemplateAbstractLobCreatingPreparedStatementCallback的实现。它实现了一种方法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上调用setBlobAsBinaryStreamsetClobAsAsciiStreamsetClobAsCharacterStream方法,则可以选择为contentLength参数指定负值。如果指定的内容长度为负数,则DefaultLobHandler使用不带 length 参数的 set-stream 方法的 JDBC 4.0 变体。否则,它将指定的长度传递给驱动程序。

现在是时候从数据库中读取 LOB 数据了。同样,您使用具有相同实例变量lobHandlerJdbcTemplate和对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);
    }
}

image-20200924165710774

image-20200924170737244

posted @ 2020-09-24 17:10  天宇轩-王  阅读(537)  评论(0编辑  收藏  举报