Spring JdbcTemplate RowCallbackHandler和RowMapper<T>的比较

来源:互联网 发布:电视直播软件哪个最好 编辑:程序博客网 时间:2024/06/06 02:49

从功能上讲,RowCallbackHandler和RowMapper没有太大的区别,它们都是用于定义结果集行的读取逻辑,将ResultSet中的数据映射到对象或者List中

RowCallbackHandler接口实现类可以是有状态的,而RowMapper的实现类应该是无状态的。如果RowCallbackHandler实现类是有状态的,用户就不能在多个地方复用,只有无状态的实例都能在不同的地方复用。

比如,Spring有一个RowCallbackHandler的实现类是RowCountCallbackHandler,可以计算结果集行数:

RowCountCallbackHandler countCallback = new RowCountCallbackHandler();jdbcTemplate.query("select * from user", countCallback);int rowCount = countCallback.getRowCount();

可见RowCountCallbackHandler包含了一个记录结果集行数的状态,在多线程的环境中,如果没有进行特殊的处理,就不能在多个地方复用countCallback实例。

Spring也提供了几个RowMapper实现类,如ColumnMapRowMapper和SingleColumnRowMapper。ColumnMapRowMapper将结果集中的每一行映射为一个Map,SingleColumnRowMapper将结果集中的某一列映射为一个Object。它们都只是定义了映射逻辑,而没有保持状态。

我们知道,通过JDBC查询返回一个ResultSet结果集时,JDBC并不会一次性将所有匹配的数据都加载到JVM中,而是只返回同一批次的数据(由JDBC驱动程序决定,如Oracle的JDBC驱动程序默认返回10行数据),当通过ResultSet#next()游标流动结果集超过数据范围时,JDBC再获取一批数据。这样以一种“批量化+串行化”的处理方式避免大结果集处理时JVM内存的过大开销。

当处理大结果集数据时,如果使用RowMapper,则虽然获取数据的过程是串行化的,但是结果集中的所有数据最终都会映射并汇总成一个List对象,占用大量的JVM内存,甚至可以直接引发OutOfMemoryException异常。这里应该使用RowCallbackHandler接口,在processRow接口方法内部处理结果集数据。

当使用RowCallbackHandler接口时,如果结果集中没有数据,并不会抛出异常,只是此时RowCallbackHandler回调接口中定义的处理逻辑没有得到调用罢了。

0 0
原创粉丝点击