【问题标题】:java.sql.SQLException: ResultSet closed when updating based on the order of definition in the main classjava.sql.SQLException:根据主类中定义的顺序更新时ResultSet关闭
【发布时间】:2021-03-16 13:33:05
【问题描述】:

我有一个类将连接到它自己的 SQLite 数据库并具有与数据库交互的功能。在我的代码customerDBmerchantDB 中有这个类的两个实例。出于某种原因,如果我尝试在类的另一个实例定义之后调用addBalance();reduceBalance(); 函数,则在主类中首先定义的实例将引发错误。

我在这种情况下得到的错误是:

线程“main”java.sql.SQLException 中的异常:ResultSet 已关闭

当我最初尝试稍后在我的主程序中调用 addBalance(); 时,我收到了错误:

线程“main”java.sql.SQLException 中的异常:数据库连接已关闭

我在我的 Java 程序中使用 JBDC 库,并且数据库中的 users 表在两个数据库中具有完全相同的布局。任何帮助将不胜感激。

Users.db

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

public class UsersDB {
    private static Connection conn = null;
    
    private boolean loggedIn = false;
    private boolean merchant = false;
    private String username;
    private float balance;
    
    public UsersDB(String dbName, boolean merchant) {
        this.merchant = merchant;
        // try to connect to DB
        try {
            Class.forName("org.sqlite.JDBC");
            conn = DriverManager.getConnection("jdbc:sqlite:" + dbName);
        } catch (Exception e) {
            System.out.println("Error - " + e.getMessage());
        }
    }
    
    public void login(String username, String password) throws NoSuchAlgorithmException, SQLException {
        
        // Check the fields contain data and that the user is not already logged in
        if (!Util.isNullOrEmpty(username) && !Util.isNullOrEmpty(password) && loggedIn == false) {
            ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM users WHERE username = '" + username + "'");
            
            // Check if username exists
            if (rs.next()) {
                String passwordInDB = rs.getString("password");
                
                MessageDigest digest = MessageDigest.getInstance("SHA-256");
                byte[] passwordHash = digest.digest(password.getBytes(StandardCharsets.UTF_8));
                
                // Check if passwords match
                if (Util.bytesToHex(passwordHash).equals(passwordInDB)) {
                    loggedIn = true;
                    
                    this.username = username;
                    balance = rs.getFloat("balance");
                    System.out.println("Successful login, " + this.username);
                }
            } else {
                System.out.println("Incorrect Username or Password");
            }
            
        } else {
            System.out.println("Sorry, there was an error logging in!");
        }
    }
    
    public float getBalance() throws SQLException {
        if (loggedIn) {
            ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM users WHERE username = '" + username + "'");          
            return rs.getFloat("balance");          
        }
        else {
            System.out.println("Action may not be performed. User must be logged in.");
        }
        return 0;
    }
    
    public void reduceBalance(float price) throws Exception {
        // User must be logged in to update balance
        // Price must be valid and not exceed the user's balance
        if (loggedIn && price > 0 && getBalance() >= price) {
            float newBalance = balance - price;
            conn.createStatement().executeUpdate("UPDATE users SET balance = " + newBalance + " WHERE username = '" + username + "'");
            // Update the value of balance to the new once stored in the database
            balance = getBalance();
            if (balance != newBalance) {
                throw new Exception("Balance Update Failed");
            } else {
                System.out.println("Customer balance decreased by " + price);
                System.out.println("");
            }
        }
        else {
            System.out.println("Cannot reduce balance");
            System.out.println("");
        }
    }
    
    public void addBalance(float price) throws Exception {
        if (loggedIn && price > 0) {
            float newBalance = balance + price;
            conn.createStatement().executeUpdate("UPDATE users SET balance = " + newBalance + " WHERE username = '" + username + "'");
            // Update the value of balance to the new once stored in the database
            balance = getBalance();
            if (balance != newBalance) {
                throw new Exception("Balance Update Failed");
            }
        } else {
            System.out.println("Cannot add balance");
        }
    }
    
    public boolean isLoggedIn() {
        return loggedIn;
    }
    
    public boolean isMerchant() {
        return merchant;
    }
    
    public void closeConnection() throws SQLException {
        conn.close();
    }
}

Definition

UsersDB merchantDB = new UsersDB("Merchants.db", true);
        merchantDB.login("merchant", "merchantpass");
        // Works
        merchantDB.addBalance(20);
        
        UsersDB customerDB = new UsersDB("Customers.db", false);
        customerDB.login("test", "testpass");   
        
        // Does not work
        merchantDB.addBalance(20);

【问题讨论】:

  • 发布您收到的错误消息。
  • @forpas 我已更新问题以包含错误消息。

标签: java database sqlite connection


【解决方案1】:

您已将连接定义为静态:

private static Connection conn = null;

这意味着UsersDB 类的所有实例都将使用相同的连接。

从其定义中删除关键字static

【讨论】:

  • 我不敢相信我没有看到这个 - 这解释了为什么在关闭与 customerDB 的连接后错误消息变为连接关闭。谢谢。
猜你喜欢
  • 1970-01-01
  • 2017-04-16
  • 2011-06-19
  • 1970-01-01
  • 2014-05-02
  • 1970-01-01
  • 1970-01-01
  • 2017-11-22
  • 2013-10-30
相关资源
最近更新 更多