0

MySQL最后一讲:JDBC 编程 - java - 细节狂魔

 2 years ago
source link: https://blog.csdn.net/DarkAndGrey/article/details/123533750
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

JDBC编程是什么?

在这里插入图片描述


怎么写一个JDBC的代码?

1、使用idea创建项目 - 学Java的,可以不看。

就是创建一个普通的 java 项目
在这里插入图片描述
在这里插入图片描述


前面说到过 JDCB 编程 需要用到 MySQL 的 “数据库驱动包”。
就是把 MySQL自身的 API 给转换成 JDBC 风格的 API
驱动包 是 mysql 官方提供的。
需要自己去MySQL的官方网站里下载驱动包
注意!虽然 MySQL 被 Oracle 给收购了,但还是取 MySQL的官网去下载。(因为 在 Oracle 网上 下载很麻烦)
不过不用担心,既然被收购了, MySQL的官网 就等于 Oracle 的一部分。所以不用担心下载到 盗版。
网址:https://mvnrepository.com/
在这里插入图片描述
更好的办法,就是去使用 Java - maven 中央仓库 来下载(就类似 手机的自带软件商店一样,下载软件不需要去官网上下载了,这里不做讲解,后面会专门写一篇关于 maven 的 博客)


j将下载好的驱动包导入项目中
在这里插入图片描述


接下来咱们的代码中,会见到很多新的类和新的方法。
不要慌,勇于接受它。
而且实际上 JDBC 编程非常简单,就是一个模板。就是起初接触的时候,接触到新的类有多而已。


在这里插入图片描述


JDBC 编程 的 基本流程


1、创建 DataSource 对象,这个对象描述了数据库服务器在哪

DataSource 数据源嘛,我们数据都来自于服务器,服务器就是数据的来源。
而 DataSource 的作用就是描述 数据库服务器在哪。知识点:向下/向下转型
在这里插入图片描述
回到最初的代码
在这里插入图片描述
现在我们要思考的问题:这三个括号中需要填入什么?


第一个括号:setURL()

在这里插入图片描述


2、setUser()

在这里插入图片描述


3、setPassword()

在这里插入图片描述


2、让代码和数据库服务器建立连接

操作1,只是帮我们确定了数据的位置。还没有真正的访问数据。
换一个通俗的说法:“操作1” 发短信告诉我们去哪里拿快递,但是呢!我们可以马上去,或者过几天去。
也就是说,我们只是知道了在哪里拿快递,实际上我们还没有拿到手。
放在 JDBC 中,就是告诉了你数据库服务器的位置,但是还没有真正的去访问数据。
在这里插入图片描述


3、进行操作数据库:以插入数据为例

关键所在就是构造一个 SQL 语句。
知识铺垫:异常
在这里插入图片描述


4、执行SQL

真正访问数据库服务器,插入数据。
在这里插入图片描述


5、此时 SQL 已经执行完毕,然后需要我们去释放资源

知识铺垫:资源释放。类似C语言中的动态开辟的空间需要通过free来释放空间
在这里插入图片描述
这是因为当创建好先关的链接之后,JVM 就会从系统这里申请到一些硬件资源。
这些资源,不用了就需要释放。
另外,释放资源是有先后顺序的。
需要先释放 preparedStatement,再去释放 connection。
(先创建的后释放,后创建的先释放)
举一个很形象的例子。
开冰箱拿东西。
先开冰箱门,再打开盒子。
拿完东西后,
先关上盒子,再关门。;
差不多就是意思。


总程序 - 初始版本 - insert 插入操作

写到这里,就已经写完一个基本的JDBC程序。
见到了一些新的概念(新的类)
DataSource/MysqlDataSource: 用来描述数据源,数据库的地址,端口,用户名、密码

Connection:表示数据库连接。
核心方法:getConnection

PreparedStatement:就通过这个对象来描述我们要执行的SQL语句。
核心方法:prepareStatement


SQL语句执行的核心方法
insert、delete、update :executeUpdate 方法
select:executeQuery


import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource; // JDBC 所在的包,用于提供 JDBC 的 类和方法。
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TestJDBC {
    public static void main(String[] args) throws SQLException {
        // 1、创建好数据源
        // DataSource 就是 JDBC 当中一个重要的 “类”(实际上它是接口)
        DataSource dataSource = new MysqlDataSource();
        // 设置数据库所在的地址
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java?characterEncoding=utf8&useSSL=false");
        // 设置 登录数据库的用户名
        ((MysqlDataSource)dataSource).setUser("root");
        //  设置登录数据库的密码
        ((MysqlDataSource)dataSource).setPassword("123456");


        //2、让代码与数据库服务器建立连接
        Connection connection = dataSource.getConnection();

        //进行操作数据库:以插入数据为例
        //关键所在就是构造一个 SQL 语句。
        String sql = "insert into student values(1,'张三')";
        //但是呢,光有一个String类型的SQL还不行。需要把这个String 包装成一个“语句对象”。
        PreparedStatement preparedStatement= connection.prepareStatement(sql);

        //4、执行SQL:真正访问数据库服务器,插入数据
        // SQL 里面的 insert、update、delete,都是是哦用 executeUpdate 方法
        // 【可以这么理解:这三操作其实都是在更新数据。而 executeUpdate 的中文意思就是执行更新】
        //  select 很特殊,使用的是 executeQuery 方法。
        // 【而 select 不涉及数据更新操作,它只是查询数据的内容。executeQuery的中文意思就是 执行询问/执行查询】
        int ret = preparedStatement.executeUpdate();
        //  preparedStatement.executeUpdate() 就是拿着我们构造好的 语句对象去进行相应的操作。
        // 并且它会返回一个整数,意思就是 这个操作 影响到了几行
        System.out.println(ret);

        //5、此时 SQL 已经执行完毕,然后需要我们去释放资源
        preparedStatement.close();
        connection.close();
    }
}
newCodeMoreWhite.png

上面的代码执行多少次,它就会插入多少行记录/数据。

在这里插入图片描述


构造SQL语句的优化

在这里插入图片描述


优化后的总程序 - insert 插入操作

在这里插入图片描述


在这里插入图片描述


小拓展:获取连接失败的原因

1、数据库的地址不对
2、端口号不对
3、数据库名不对
4、用户名不对
5、密码不对
6、其他情况


delete 删除操作

由于非常简单,和上面 insert 操作几乎一毛一样。就是修改 构造的SQL语句就行了。
我就不讲太多,直接上程序。

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;

public class TestJDBCDelete {
    public static void main(String[] args) throws SQLException {
        Scanner sc = new Scanner(System.in);
        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("123456");

        Connection connection = dataSource.getConnection();
        System.out.println("请输入要删除信息人的ID:");
        int id = sc.nextInt();

        String sql = "delete from student where id = ?";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        preparedStatement.setInt(1,id);

        int ret = preparedStatement.executeUpdate();
        System.out.println(ret);

        preparedStatement.close();
        connection.close();
        sc.close();
    }
}
newCodeMoreWhite.png

在这里插入图片描述


update 更新操作

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;

public class TestJDBCUpdate {
    public static void main(String[] args) throws SQLException {
        Scanner sc = new Scanner(System.in);
        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("123456");
        Connection connection = dataSource.getConnection();
        System.out.println("请输入修改信息人的ID:");
        int id = sc.nextInt();
        System.out.println("请输入修改姓名:");
        String name = sc.next();
        String sql = "update student set name = ? where id = ?";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setString(1,name);
        preparedStatement.setInt(2,id);
        System.out.println("preparedStatement:"+preparedStatement);
        int ret = preparedStatement.executeUpdate();
        System.out.println(ret);

        preparedStatement.close();
        connection.close();
        sc.close();
    }
}

newCodeMoreWhite.png

在这里插入图片描述


优化后的总程序 - select 查询操作

插叙的写法有些不同,首先,查询多出一个步骤:遍历结果集/临时表中数据(把结果中的数据给获取到)
在这里插入图片描述


import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestJDBCSelect {
    public static void main(String[] args) throws SQLException {
        //1、创建数据源
        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("123456");

        // 2、建立连接
        Connection connection = dataSource.getConnection();

        //3、构建SQL语句
        String sql = "select * from student";

        //4、将字符串风格的SQL语句包装秤 “语句对象"
        PreparedStatement preparedStatement= connection.prepareStatement(sql);

        //5、执行SQL语句,与之不同的是 select 的执行方法是 executeQuery()
        //查询操作我们都知道它返回是一个临时表。
        // 所以用来接收的变量类型 不能是 常见的数据类型了。
        ResultSet resultSet = preparedStatement.executeQuery();
        //executeQuery 的返回值类型根据  点击进入原码就可以知道为 ResultSet 类型。
        // 获取数据的思路:先获取到每一行,再获取到这一行中的若干列

        // 通过next 方法,来获取到一行记录,同时把光标往后移动一行。
        // 如果遍历到表的结束为止,此处的 next 直接返回 false.
        // 循环条件为假,终止循环。
        // 下面是 student 表 全列查询的结果
//              +------+--------+
//              | id   | name   |
//              +------+--------+
//              |    2 | 王五   |
//              |    6 | 赵六   |
//              +------+--------+
        while(resultSet.next()){
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            System.out.println("id = " + id + ", name = " + name);
        }
        preparedStatement.close();
        connection.close();
    }
}
newCodeMoreWhite.png

拓展: 基于反射来描述数据库服务器的位置

// 加载JDBC驱动程序:反射,这样调用初始化com.mysql.jdbc.Driver类,即将该类加载到JVM方法区,并执行该类的静态方法块、静态属性。
Class.forName("com.mysql.jdbc.Driver");
// 创建数据库连接
Connection connection =DriverManager.getConnection("jdbc:mysql://localhost:3306/test?
user=root&password=root&useUnicode=true&characterEncoding=UTF-8");

localhost 就是 127.0.0.1
首先我要声明一点:非常不推荐这样去写
1、因为 反射 属于编程中的“非常规手段”,反射如果在代码中使用的多了,是非常影响代码的可读性的。也不利于IDEA对代码进行解析校验。
2、这种写法相比于DataSource来说,DataSource 更好用。
因为DataSource内置了连接池,在频繁 创建/断开 链接的时候,这里的DataSource就要比 DriverManager的方式更加高效。

这是因为 DataSource 中涉及到一个关键字 “池”【连接池 - Connection pool】,学过JavaSE的朋友,是不是觉得很熟悉,跟我们在学String的时候, 接触的 字符串常量池 很像。其实两者含义完全相同。
池的作用:就是把你可能用到东西都装在一个“池子”里,你要用的时候,直接往“池”里拿。池里有,它就直接给你,而且相当于给你可一个克隆的备份(就是说给了你之后,池里面还有,你下回还可以接着用),没有就创建一个给你。
所以DataSource更加高效!!!!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK