【问题标题】:How to rewrite jdbcTemplate query using JDK8 features?如何使用 JDK8 功能重写 jdbcTemplate 查询?
【发布时间】:2016-07-28 08:39:57
【问题描述】:

这是代码。假设数据库中有很多大图像,所以我想一次只在内存中保留一个。如何使用 JDK 8 功能(如 lambda 和流)编写此代码?

我开始使用这些,但它一直失败(来自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)
    ) );

这只是在开始“流式传输”它们之前加载所有行。

【问题讨论】:

    标签: spring lambda stream java-8 jdbctemplate


    【解决方案1】:

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

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

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

    【讨论】:

    • 是的,很好的解决方案,错过了这个。我会测试它是否真的有效;)不知何故,我一直相信查询正在返回流(能够)的东西,但显然不是。
    • 操作,Caused by: org.postgresql.util.PSQLException: Ran out of memory retrieving query results.
    【解决方案2】:

    您可以将 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;
        }
    );
    

    【讨论】:

      猜你喜欢
      • 2021-03-18
      • 2020-12-26
      • 1970-01-01
      • 1970-01-01
      • 2021-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-01
      相关资源
      最近更新 更多