Question

I'm trying to accommodate to Spring JDBC, but what bugs me is using these anonymous classes, where we cannot pass any local variables unless they are final which might be easy to arrange, but what about if I need to loop an array or collection ? I cannot declare "FedModel fm" to be final as it gets reinitialized in the loop, but I need to call the execute method 100 times. This is concrete scenario where I have the problem, cause I don't know any other way how to insert BLOB into a database.

 for (int i = 0; i < fedModels.size(); i++) {
        FedModel fm = fedModels.get(i);

        jdbcTemplate.execute("INSERT INTO items (name, video_blob) VALUES (?, ?)",
                  new AbstractLobCreatingPreparedStatementCallback(lobHandler) {
                  protected void setValues(PreparedStatement ps, LobCreator lobCreator) 
                        throws SQLException {
                            ps.setString(1, fm.getName());
                            ps.setString(2, fm.getDifficultyLevel());
                            ps.setString(3, fm.getEquipment());
                            lobCreator.setBlobAsBinaryStream(ps, paramIndex, contentStream, contentLength);                                                     
                          }
                });

} 

The only thing I can think of, is creating a static Nested class that extends AbstractLobCreatingPreparedStatementCallback and adds constructor for fedModels so that I could do the loop inside. But it would be easier using only JDBC.

Was it helpful?

Solution

... but what bugs me is using these anonymous classes, where we cannot pass any local variables unless they are final ...

This is not Spring's fault. It is property of the Java programming language.

Basically, the Java language (at least Java 6 and earlier) does not support closures which would allow the anonymous class instance to access and update local variables in the instance's enclosing scopes. As a workaround, the language allows you to access enclosing local variables that are final. This is implemented (without closures) by copying the respective variable's values into the anonymous class instance, and storing them in hidden variables.

In your particular case, the simple solution is to declare fm as final. If you needed to access the loop variable in the anonymous class, you could declare a final copy; e.g.

for (int i = 0; i < 10; i++) {
    final int ii = i;
    new Thread(new Runnable(){
        public void run() {
            System.err.println(ii);
        }
    }).start();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top