【问题标题】:Java Swing Timer with SQL带有 SQL 的 Java Swing 计时器
【发布时间】:2012-07-07 16:32:01
【问题描述】:

我正在尝试设置一个线程,该线程每 100 毫秒循环一次,每次迭代都会查询 SQL 数据库中的表。这是我的公共静态无效主类中的内容。如何在监听器之外定义连接,只在循环中调用查询?

    // Database credentials
    final String url = "jdbc:mysql://192.168.0.0/";
    final String db = "db";
    final String driver = "com.mysql.jdbc.Driver";
    final String table = "table";
    public final Connection conn = null;

    // Define listner
    ActionListener taskPerformer = new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
            //...Perform a task...

            System.out.println("Reading Info.");
            try {
                Class.forName(driver);
                try {
                    conn = DriverManager.getConnection(url+db,"root","pass");
                    Statement st = (Statement) conn.createStatement();
                    String sql = "";
                    st.executeUpdate(sql);
                    conn.close();

                } catch (SQLException s) {
                    s.printStackTrace();
                    JOptionPane.showMessageDialog(null, "ERROR: Please try again!");
                }
            } catch (ClassNotFoundException cnfe){
                JOptionPane.showMessageDialog(null, "ERROR:");  
            }
        }
        };
    Timer timer = new Timer( 100 , taskPerformer);
    timer.setRepeats(true);
    timer.start();

    Thread.sleep(100);

}

现在它给了我以下错误:

线程“AWT-EventQueue-0”java.lang.Error 中的异常:未解决的编译问题: 最终的局部变量 conn 不能赋值,因为它是在封闭类型中定义的

【问题讨论】:

  • 其他问题:1) 你不应该在 Swing 事件线程上调用Thread.sleep(...)。 2)您应该在相对于 Swing 事件线程的后台线程中进行数据库调用。 3) 上面的代码都不应该在静态域中,在 main 方法中。顺便说一句,对@MJB 的回答加分。

标签: java sql timer


【解决方案1】:

你不想。根据 JDBC 规范,连接不是线程安全的。因此,没有理由或理由证明 Connection 变量不是线程本地的。为什么不呢?

【讨论】:

  • 我关心每次迭代连接到数据库的速度。
  • 然后使用C3P0等连接池。然后这个问题就消失了。
  • 好的。实施起来难吗?
  • 一点也不。这很简单。有关血腥细节,请参阅mchange.com/projects/c3p0。阅读第一部分。不太难吧?是的,cpds 是线程安全的,所以你可以将它存储在某个地方并使用它。
  • 最近对 JDBC 连接池的更好推荐是 boneCP。
【解决方案2】:

现在您已经对非直接问题有了答案,让我用您的直接问题来补充。你有这个:public final Connection conn = null; 这没有任何意义。您已将 null 分配给 final 变量。您可能添加了final,因为编译器抱怨您在内部类中使用了非最终变量。您可能想要实现的是延迟初始化的单例。移除final 修饰符,然后编写一个单独的同步函数来检索连接并根据需要对其进行初始化:

private Connection conn;
private synchronized Connection connection() {
  if (conn == null) conn = createConnection();
  return conn;
}

当然,您最好确保从不同时使用连接,但您的用例不需要这样做。这种简单的连接池方法的另一个问题是连接处于无效状态。

【讨论】:

  • 以这种方式而不是使用连接池进行连接存在很多问题,我无法推荐这个。
  • 我也不建议将其用于生产。不过,它可能具有教育价值。虽然我们这样做了,但像这样的手动 事务 管理更不值得推荐。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-04-04
  • 2014-05-29
  • 1970-01-01
  • 2017-05-18
  • 1970-01-01
  • 1970-01-01
  • 2014-09-14
相关资源
最近更新 更多