You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JDBC工具类连接数据库时出现Utils.connection为空的错误求助

解决JDBC工具类连接null异常的问题

问题核心原因

你遇到的Cannot invoke "java.sql.Connection.prepareStatement(String)" because "Utils.connection" is null异常,本质是数据库连接初始化的时机晚于数据库操作执行的时机。

看你的代码执行顺序:
在Contacts的main方法中,是先执行new Contacts()触发构造函数(构造函数里直接调用loadContacts()执行数据库查询),之后才调用Utils.Connect()初始化连接。所以当loadContacts执行时,Utils.connection还未被赋值,自然抛出空指针异常。


分步修复方案

1. 调整连接初始化顺序

把Utils.Connect()放到创建Contacts实例之前,确保连接先初始化完成:

public static void main(String[] args) {
    // 先初始化数据库连接
    Utils.Connect();
    frame.setContentPane(new Contacts().Main);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
    frame.setResizable(false);
    frame.setSize(500, 700);
}

2. 修复listModel变量覆盖问题

你在Contacts构造函数里重新定义了listModel局部变量,会覆盖类成员变量,导致loadContacts里的listModel.clear()抛出空指针。改成直接初始化成员变量:

public Contacts() {
    // 不要重新定义变量,直接给成员变量赋值
    listModel = new DefaultListModel<>();
    list.setModel(listModel);
    loadContacts(); 
}

3. 修正SQL参数错误

你用String.valueOf(list)作为id参数完全不合理,JList的toString返回的不是你需要的id值。如果是要查询所有联系人,直接去掉WHERE条件:

Utils.preStmt = Utils.connection.prepareStatement("SELECT * FROM contactsdb");
// 无需设置参数,直接执行查询
Utils.rs = Utils.preStmt.executeQuery();

如果需要按id查询,要先获取选中项的有效id值(比如从列表项中解析):

if (!list.isSelectionEmpty()) {
    String selectedItem = (String) list.getSelectedValue();
    // 假设列表项格式是"id 姓名 电话",解析出id
    String targetId = selectedItem.split(" ")[0];
    Utils.preStmt = Utils.connection.prepareStatement("SELECT * FROM contactsdb WHERE id =?");     
    Utils.preStmt.setString(1, targetId); 
}

4. 重构Utils类(避免后续隐患)

你的Utils用静态成员存储Connection、PreparedStatement、ResultSet,在多线程环境下会出现资源冲突,还会导致连接泄漏。建议改成以下更安全的写法:

import java.sql.*;

public class Utils { 
    private static final String DB_URL = "jdbc:mysql://localhost:3306/testdb";
    private static final String DB_USER = "root";
    private static final String DB_PWD = "";

    // 每次调用返回新的连接,避免静态成员冲突
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(DB_URL, DB_USER, DB_PWD);
    }

    // 统一关闭资源,避免泄漏
    public static void closeResources(Connection conn, PreparedStatement stmt, ResultSet rs) {
        try {
            if (rs != null) rs.close();
            if (stmt != null) stmt.close();
            if (conn != null) conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

之后在loadContacts中使用这个工具类:

public void loadContacts() { 
    String name;
    String number;
    String address;

    listModel.clear();
    Connection conn = null;
    PreparedStatement preStmt = null;
    ResultSet rs = null;

    try {
        conn = Utils.getConnection();
        preStmt = conn.prepareStatement("SELECT * FROM contactsdb");     
        rs = preStmt.executeQuery();

        while (rs.next()) {
            // 建议用列名而非索引,避免表结构变更导致错误
            name = rs.getString("name");
            number = rs.getString("number");
            address = rs.getString("address");
            listModel.addElement(name + " " + number + " " + address);
        } 
    } catch (SQLException e) {
        e.printStackTrace(); 
    } finally {
        // 确保资源一定会被关闭
        Utils.closeResources(conn, preStmt, rs);
    }
}

内容的提问来源于stack exchange,提问作者Landry Okoye

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 10:37:33