How to rewrite the jdbcTemplate query using the JDK8 features?

advertisements

Here's the code. Let's say there are many large images in the db so I want to keep only one in memory at a time. How to write this using JDK 8 features like lambda and streams?

I started using those but it kept failing ( from https://spring.io/guides/gs/relational-data-access/ and www.jooq.org/java-8-and-sql) and using ResultSetExtractor is working as intendent, but is there a way to do it without 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;
                    }
            }
    );

This is nice looking stream/lambda version which works but holds too many things in memory and gives OOME sooner or later.

 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)
    ) );

This just loads all the rows before it starts to "streaming" them.


A solution could be to move the generation of the thumbnail in the first lambda, translating directly your first example.

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

To have a structure similar to the one you tried to achieve the query method should return a stream so you don't have to collect everything before streaming.