如何使用JDK8功能重写jdbcTemplate查询?

时间:2016-07-28 08:39:58

标签: spring lambda stream java-8 jdbctemplate

这是代码。让我们说数据库中有很多大图像,所以我想一次只在内存中保留一个。如何使用像lambda和streams这样的JDK 8功能来编写它?

我开始使用它们但是它仍然失败(来自https://spring.io/guides/gs/relational-data-access/www.jooq.org/java-8-and-sql)并且使用ResultSetExtractor正在作为用户,但有没有办法在没有ResultSetExtractor的情况下执行此操作?

 jdbcTemplate.query( 
            "select id,image,mimetype from images",
            new ResultSetExtractor(){  
                @Override  
                public List extractData(ResultSet rs) throws SQLException, DataAccessException {  
                        while(rs.next()){  
                           createThumbnail( new ImageHolder(rs.getInt("id"), rs.getBytes("image"), rs.getString("mimetype") ));
                        }  
                        return null;
                    }  
            }
    );  

这是一个很好看的流/ lambda版本,它可以在内存中保存太多东西,并且迟早会给OOME。

 jdbcTemplate.query( 
             "select id,image,mimetype from images",
             (rs,rowNum)->new ImageHolder(rs.getInt("id"), rs.getBytes("image"),rs.getString("mimetype"))
    ).stream().forEach(   
                   imageHolder -> createThumbnail(imageHolder)
    ) );

这只会在开始之前加载所有行" streaming"它们。

2 个答案:

答案 0 :(得分:2)

解决方案可能是在第一个lambda中移动缩略图的生成,直接翻译你的第一个例子。

    if ($_POST['blob']) {
        if ($profile->avatar==1) {
            unlink('/images/avatars/'.$profile->avatar);
            $profile->avatar=0;
        }
        $file = base64_decode($_POST['blob']);
        $filename="avatar_".$user_id.'.'.$_POST['ext'];
        file_put_contents($_SERVER['DOCUMENT_ROOT'] ."/images/avatars/".$filename, $file);
        $profile->avatar=$filename;
    }

要获得与您尝试实现查询方法的结构类似的结构,应该返回一个流,这样您就不必在流式传输之前收集所有内容。

答案 1 :(得分:1)

您可以将JDBC Statement.setFetchSize()限制为比默认值see also some hints here更合理的值。

另一种方法是手动分页,如下所示:

int size = 10;
jdbcTemplate.query(

    // This query creates chunks of 10 and shows the low/high id value in each chunk
    "select id1, id2 "
  + "from ( "
  + "  select "
  + "    id AS id1, "
  + "    lead(id, ?) over (order by id) AS id2, "
  + "    row_number() over (order by id) rn from images) i "
  + "  from images "
  + ") i    
  + "where rn % ? = 0",
    new Object[] { size, size },
    rs1 -> {
        while (rs1.next())
            jdbcTemplate.query(
                // This query fetches only images for each chunk
                "select id, image, mimetype from images "
              + "where id >= ? and id < coalesce(?, 2147483647)",
                new Object[] { rs1.getInt(1), rs1.getInt(2) },
                rs2 -> {
                    createThumbnail(new ImageHolder(
                        rs2.getInt("id"), 
                        rs2.getBytes("image"), 
                        rs2.getString("mimetype") 
                    ));
                    return null;
                }
            );

        return null;
    }
);