Spring 匿名/回调类用于数据持久化的困难时期

发布于 2024-09-24 17:29:16 字数 1135 浏览 3 评论 0原文

我正在尝试适应 Spring JDBC,但让我烦恼的是使用这些匿名类,我们无法传递任何局部变量,除非它们是最终的,这可能很容易安排,但是如果我需要循环数组或集合怎么办? 我无法将“FedModel fm”声明为最终的,因为它在循环中重新初始化,但我需要调用执行方法 100 次。这是我遇到问题的具体场景,因为我不知道如何将 BLOB 插入数据库的任何其他方法。

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

} 

我唯一能想到的就是创建一个静态嵌套类,该类扩展 AbstractLobCreatingPreparedStatementCallback 并添加 fedModels 的构造函数,以便我可以在内部执行循环。但仅使用 JDBC 会更容易。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谁对谁错谁最难过 2024-10-01 17:29:16

...但是让我烦恼的是使用这些匿名类,我们不能传递任何局部变量,除非它们是最终的...

这不是Spring的错。它是 Java 编程语言的属性。

基本上,Java 语言(至少 Java 6 及更早版本)不支持闭包,闭包允许匿名类实例访问和更新实例封闭范围内的局部变量。作为解决方法,该语言允许您访问 final 封闭的局部变量。这是通过将相应变量的值复制到匿名类实例中并将它们存储在隐藏变量中来实现的(没有闭包)。

在您的特定情况下,简单的解决方案是将 fm 声明为 final。如果需要访问匿名类中的循环变量,可以声明一个最终副本;例如

for (int i = 0; i < 10; i++) {
    final int ii = i;
    new Thread(new Runnable(){
        public void run() {
            System.err.println(ii);
        }
    }).start();
}

... 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();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文