实操 JDBC 连接 MySql 数据库,异常 java.sql.SQLException:No suitable driver found for jdbc:..(Java 从自学到就业 第20天)

Java 学习记录 第二十天

由于本渣渣是前端转行Java,所以编辑器的选择就直接用 webstorm 同公司的 idea
接下来的知识梳理有一部分会借鉴大佬 廖雪峰的博客

学习目标

了解 JDBC 原理,并实际操作连接 MySql 数据库


学习内容

  • 简述 JDBC 概念
  • 实操 JDBC 连接 MySql 数据库
  • 使用 JDBC 执行数据库 CRUD 操作

简述 JDBC 概念

什么是JDBC?JDBC是Java DataBase Connectivity的缩写,它是Java程序访问数据库的标准接口。
使用 Java 程序访问数据库时,Java 代码并不是直接通过 TCP 连接去访问数据库,而是通过 JDBC 接口来访问,而 JDBC 接口则通过 JDBC 驱动来实现真正对数据库的访问。
例如,我们在 Java 代码中如果要访问 MySQL,那么必须编写代码操作 JDBC 接口。注意到 JDBC 接口是 Java 标准库自带的,所以可以直接编译。而具体的 JDBC 驱动是由数据库厂商提供的,例如,MySQL 的 JDBC 驱动由 Oracle 提供。因此,访问某个具体的数据库,我们只需要引入该厂商提供的 JDBC 驱动,就可以通过 JDBC 接口来访问,这样保证了 Java 程序编写的是一套数据库访问代码,却可以访问各种不同的数据库,因为他们都提供了标准的 JDBC 驱动。

使用 JDBC 的好处是:

  1. 各数据库厂商使用相同的接口,Java 代码不需要针对不同数据库分别开发;
  2. Java 程序编译期仅依赖 java.sql 包,不依赖具体数据库的 jar 包;
  3. 可随时替换底层数据库,访问数据库的 Java 代码基本不变。

实操 JDBC 连接 MySql 数据库

昨天已经尝试了怎么用 IDEA 的 Database 工具创建 MysSql 数据库。今天就是用 JDBC 来对昨天创建的 hero 表进行操作。

import java.sql.*;

public class Test2 {

    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://localhost:3306/test";

    static final String USER = "root";
    static final String PASS = "123123";

    public static void main(String[] args) throws SQLException,Exception {
        Connection conn = null;
        Statement stmt = null;

        System.out.println("连接数据库...");
        conn = DriverManager.getConnection(DB_URL, USER, PASS);

        System.out.println("实例化 Statement 对象...");
        stmt = conn.createStatement();
        String sql;
        sql = "SELECT * from hero";
        ResultSet rs = stmt.executeQuery(sql);

        while (rs.next()) {
            Integer id = rs.getInt("id");
            String name = rs.getString("name");
            Integer hp = rs.getInt("hp");
            Integer mp = rs.getInt("mp");
            Integer lv = rs.getInt("lv");

            System.out.println("ID:" + id + ", 英雄名称:" + name + ", 血量:" + hp + ",蓝量:" + mp + ",等级:" + lv + "\n");
        }

        rs.close();
        stmt.close();
        conn.close();
        System.out.println("程序结束...");
    }
}

上述代码就是一个简单的数据库操作,通过 JDBC 连接 MySql 数据库并查找出 hero 表中的所有数据,最后在输出到面板,输出结果如下:
王思聪舔狗秘籍
这里需要注意的是,在执行 JDBC 操作的时候需要依赖对应数据库的 jar包。

  • 这里我选择的是 MySql 官方的 mysql-connector-java-5.1.49-bin
  • 当然也可以选择其他的版本,如果选择了高于 8.0 版本的 MySql
  • 需要把上述代码中的 JDBC_DRIVER 常量值修改为:com.mysql.cj.jdbc.Driver

然而下载完对应的 jar 包,当然还是要引入到项目中去,不然运行代码还是会抛出异常:
Exception in thread “main” java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/test
这坑自己也是爬了半天,下面记录下怎么将 jar 包引入到项目中:
File -> Project Structure -> Modules -> 有个 + 号点击 -> Library -> Kotlin/JS -> 选择你 jar 包的存放路径然后一直 ok 下去
最后的界面吐下图所示:

舔狗问卷正确答案
上图的 ok在点下去就完成了 jar包的导入了,当然这只是演示哈,实际开发话用 maven直接配置依赖会比较多…’

使用 JDBC 执行数据库 CRUD 操作

什么是 CRUD:这是行话,讲白了就是对数据的增删改查(对应全程 Create,Retrieve,Update、Delete)
下面将使用 JDBC 来对之前的 hero 表进行以上操作

import java.sql.*;

class CreatJDBC {
    private static final String DRIVER = "com.mysql.jdbc.Driver";
    private static final String URL = "jdbc:mysql://localhost:3306/test?characterEncoding=utf8";
    private static final String USER = "root";
    private static final String PASS = "123123";

    private static Connection conn = null;
    private static Statement stmt = null;
    private static ResultSet rs = null;
    private static PreparedStatement ps = null;

    public void creatStmt() throws SQLException, ClassNotFoundException {
        Class.forName(DRIVER);

        try {
            this.conn = DriverManager.getConnection(URL, USER, PASS);
            this.stmt = conn.createStatement();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public CreatJDBC() throws SQLException, ClassNotFoundException {
        this.creatStmt();
    }

    public void closeAll() throws SQLException {
        this.conn.close();
        this.stmt.close();
    }

    public void jdbcPreparedStatementAdd(String sql) throws SQLException, ClassNotFoundException {
        try {
            this.ps = this.conn.prepareStatement(sql);
            this.ps.setObject(1, 9);
            this.ps.setObject(2, "李元芳");
            this.ps.setObject(3, 998);
            this.ps.setObject(4, 322);
            this.ps.setObject(5, 18);
            System.out.println("操作的行数:" + this.ps.executeUpdate() + ",操作后数据如下:");
            this.jdbcResultSet("SELECT * FROM hero");
        } finally {
            this.closeAll();
            this.ps.close();
        }
    }

    public void jdbcPreparedStatementUpdate(String sql) throws SQLException, ClassNotFoundException {
        try {
            this.ps = this.conn.prepareStatement(sql);
            this.ps.setObject(1, "虞姬");
            this.ps.setObject(2, 5);
            System.out.println("操作的行数:" + this.ps.executeUpdate() + ",操作后数据如下:");
            this.jdbcResultSet("SELECT * FROM hero");
        } finally {
            this.closeAll();
            this.ps.close();
        }
    }

    public void jdbcPreparedStatementDel(String sql) throws SQLException, ClassNotFoundException {
        try {
            this.ps = this.conn.prepareStatement(sql);
            this.ps.setObject(1, 7);
            System.out.println("操作的行数:" + this.ps.executeUpdate() + ",操作后数据如下:");
            this.jdbcResultSet("SELECT * FROM hero");
        } finally {
            this.closeAll();
            this.ps.close();
        }
    }

    public void jdbcResultSet(String sql) throws SQLException, ClassNotFoundException {
        try {
            this.rs = this.stmt.executeQuery(sql);
            while (this.rs.next()) {
                Integer id = this.rs.getInt("id");
                Integer hp = this.rs.getInt("hp");
                Integer mp = this.rs.getInt("mp");
                Integer lv = this.rs.getInt("lv");
                String name = this.rs.getString("name");
                System.out.println("ID:" + id +
                        ", 英雄名称:" + name +
                        ", 血量:" + hp +
                        ",蓝量:" + mp +
                        ",等级:" + lv);
            }
        } finally {
            this.closeAll();
            this.rs.close();
        }
    }
}

public class Test1 {
    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        CreatJDBC creatJDBC_1 = new CreatJDBC();
        creatJDBC_1.jdbcResultSet("SELECT * FROM hero");

        CreatJDBC creatJDBC_2 = new CreatJDBC();
        creatJDBC_2.jdbcPreparedStatementAdd("INSERT INTO hero (id, name, hp, mp, lv) VALUES (?,?,?,?,?)");

        CreatJDBC creatJDBC_3 = new CreatJDBC();
        creatJDBC_3.jdbcPreparedStatementUpdate("UPDATE hero SET name=? WHERE ID=?");

        CreatJDBC creatJDBC_4 = new CreatJDBC();
        creatJDBC_4.jdbcPreparedStatementDel("DELETE FROM hero WHERE id=?");
    }
}

在写这段代码的时候遇到以下问题:

  1. 本意是想将 PreparedStatement 操作都封装成一个方法,因为在使用 JDBC 执行 INSERT、UPDATE、DELETE 都可视为更新操作。(可是发现他的语法需要 sql 语句配合语法糖再执行 setObject() 方法,暂时封装不出来,有时间再试试怎么进一步优化…)
  2. 实例的构造器也没有封装好,这样会产生每一个实例只能操作一次的情况,操作之后就会自动执行 close() 方法把 Statement 干掉,就没有办法再继续执行下一步的操作,所以我只能声明多个实例来做演示。(异常信息:Exception in thread “main” java.sql.SQLException: No operations allowed after statement closed.
  3. PreparedStatement 在执行存入中文操作的时候出现了 “???” 的情况,后来才发现原来在声明 url 的时候没有添加中文编码参数,修改常量 URL 的值为:jdbc:mysql://localhost:3306/test?characterEncoding=utf8
  4. Parameter 语法糖的参数列表下标是从 1 开始,而且需要严格对应数据格式,比如在添加的时候前面声明了几个参数后面就必须跟几个?,不然就会抛出异常:Parameter index out of range (1 > number of parameters, which is 0).

Exception in thread "main" java.lang.NullPointerException
最后终于是成功运行了,真是可喜可贺!!!

Exception in thread "main" java.sql.SQLException: Column count doesn't match value count at row 1



自学不易,点赞鼓励。

谢谢各位看官,如果有哪里写错的还望指出来哈,共同进步。

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Only Double J

自学不易,希望鼓励。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值