JDBC帮助类的封装

JDBC帮助类的封装

通过前面的学习可以发现,JDBC操作重复代码非常多,完全可以把它封装起来。

完整代码

package util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JdbcUtil {
    private Connection conn = null;
    private PreparedStatement stmt = null;
    private ResultSet rs = null;
    private static String driver = "com.mysql.jdbc.Driver";
    private String url = "jdbc:mysql://localhost:3306/Student";
    private String user = "root";
    private String password = "root";

    /**
     * 加载驱动(静态代码块,类加载时执行一次)
     */
    static {

    }

    /**
     * 获取数据库连接
     */
    public Connection getCon() {
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            conn = (Connection) DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

    /**
     * 增删改通用方法
     * @param sql
     * @param obj
     */
    public int update(String sql, Object... obj) {
        int count = 0;
        conn = getCon();
        try {
            stmt = conn.prepareStatement(sql);
            if (obj != null) {
                for (int i = 0; i < obj.length; i++) {
                    stmt.setObject(i + 1, obj[i]);
                }
            }
            count = stmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close();
        }
        return count;
    }

    /**
     * 查询通用方法
     * @param sql
     * @param obj
     */
    public ResultSet Query(String sql, Object... obj) {
        conn = getCon();
        try {
            stmt = conn.prepareStatement(sql);
            if (obj != null) {
                for (int i = 0; i < obj.length; i++) {
                    stmt.setObject(i + 1, obj[i]);
                }
            }
            rs = stmt.executeQuery();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        // 注意:查询后不能在这里关闭连接,否则ResultSet就拿不到数据了
        return rs;
    }

    /**
     * 关闭资源
     */
    public void close() {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (stmt != null) {
                    stmt.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                if (conn != null) {
                    try {
                        conn.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}Code language: JavaScript (javascript)

补充说明

  • 驱动类名写的是 com.mysql.jdbc.Driver,这是 mysql-connector-java 5.x 的写法。如果用的是 8.x 版本,需要改成 com.mysql.cj.jdbc.Driver
  • 静态代码块里原本应该写 Class.forName(driver),这里留空了,实际应该补上:
static {
    try {
        Class.forName(driver);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}Code language: JavaScript (javascript)

然后把 getCon() 里的 Class.forName(driver) 删掉,驱动只需加载一次

  • update() 方法用可变参数 Object... obj 接收 ? 的值,内部循环调用 setObject() 设置参数,适用于 insert、update、delete 和 DDL
  • Query() 方法返回 ResultSet,调用方拿到结果集遍历完之后需要手动调用 close() 关闭资源,不能在 Query() 内部关闭
  • 每次调用 getCon() 都会新建一个连接,频繁创建连接开销大。实际项目中应该用数据库连接池(如 Druid、HikariCP、DBCP)替代
  • 这个工具类适合学习阶段使用,生产环境建议用 MyBatis、JPA 等成熟框架,或者至少加上连接池和事务管理

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注