一文速通Java的JDBC编程
目录
🐽JDBC的引入
什么是API
JDBC的概念及作用
🍇准备工作
数据库驱动包
下载第三方库
🐾JDBC 使用
将jar包导入项目
通过代码使用JDBC的API
(1)创建数据源对象并设置属性
(2)和数据库服务器建立网络连接
(3)程序构造SQL语句
(4)把SQL发送到服务器上进行执行
update、insert、delete语句
select语句
(5)释放资源
🐽JDBC的引入
针对数据库的操作,SQL实际上工作中,很少会直接通过命令行/图形化客户端来操作数据库,更多的是,通过代码(C++,Java,Python,Go…)操作数据库。但我们前面学到的SQL语句都不会白学哈,即使是通过代码操作数据库,仍然会用到SQL。
什么是API
🌈对于JDBC的引入首先要知道什么是API
Application Programming Interface应用程序编程接口
咱们写代码,一般不是从0开始写的,会调用一些别人写好的代码,别人写好的代码,就称为"库",这些代码里提供的一些类/方法/函数就可以称为API了.
学JavaSE/数据结构的时候,其实也接触到过,我们会用到不少Java标准库提供的API
String、List、Random、Scanner......还有一个专门的Java API文档
通过代码操作数据库的前提就是,数据库首先要提供一组API供其他的程序来调用
问题来了,数据库,有很多种Oracle,Mysql,SQL Server.......这些数据库,提供的API是一样的吗?要看类的名字里面的方法方法的作用是否一样。当然是不一样的,因为这些数据库分别是不同的公司不同的程序员研究出来的。既然这样,每个数据库提供的API都是自成一套体系,程序员在一旦切换数据库后,岂不是要学习一套新的API的使用吗?在谁都不服谁时,江湖大哥Java自身制定了一套API标准,各种数据库都要把自己的API转换成和Java这一套兼容的API。这一套标准的API我们就称为JDBC。
JDBC的概念及作用
JDBC,即Java Database Connectivity,java数据库连接。是一种用于执行SQL语句的Java API,它是Java中的数据库连接规范。这个API由 java.sql.*,javax.sql.* 包中的一些类和接口组成,它为Java开发人员操作数据库提供了一个标准的API,可以为多种关系数据库提供统一访问。
在Java JDBC编程中对数据库的操作均使用JDK自带的API统一处理,通常与特定数据库的驱动类是完全解耦的。所以掌握Java JDBC API (位于 java.sql 包下) 即可掌握Java数据库编程。
🍇准备工作
数据库驱动包
不同的数据库,对应不同的编程语言提供了不同的数据库驱动包,如:MySQL提供了Java的驱动包mysql-connector-java,需要基于Java操作MySQL即需要该驱动包。同样的,要基于Java操作Oracle数据库则需要Oracle的数据库驱动包ojdbc。
下载第三方库
MySQL本身的API是C语言的API,就需要把原生C的API转换成兼容JDBC的Java的API。MySQL官方提供了一个mysql-connector-java驱动包,就可以完成上述转换。mysql-connector-java不是mysql自带,也不是java自带的。需要通过第三方的途径,把这个东西下载下来并且导入到自己的项目中。
下载一个第三方库主要有三种途径:
1)去官方网站 Oracle官网
2)去github
3)去maven中央仓库
前两种都比较麻烦,第三种方便快速,类似于手机APP应用商店
这里给出链接来教大家怎么下载🔗🔗🔗,验证需要时间请耐心等待哦💞💞💞
mysql 5.7 经典版就行了,mysql 8 经典版 最新版都可以,我这里下载的是MySQL版本是5.7,所以我选择下面的经典版,点击大黑粗体进去即可
如果mysql服务器是8系列connector也必须使用8版本,如果mysql服务器是5系列connector也必须使用5版本,一点要保证版本的匹配,查看自己下载的MySQL是哪个版本就不用我教了吧。🙈🙈
点击jar就会触发下载
🐾JDBC 使用
将jar包导入项目
☔️首先解释下什么是jar包
java中第三方库通常是以jar后缀的文件来提供的,称为jar包,本质上就是一个类似于.rar这样的压缩包,只不过这里放的内容是java的一些.class文件
java代码是java文件通过javac编译之后,每个java就会得到一个.class二进制字节码文件,
一个程序,可能会有很多类,会有很多.class文件,为了方便,于是就可以把这些.class打成压缩包也就是jar。
现在我们来学习怎么把jar包导入到自己的项目中去,至于用idea怎么创建一个项目我就不教了
1️⃣先在项目中创建一个目录,名字随便起,但是不要带有中文/特殊字符
我之所以起为lib,那是因为lib即library意思是库,即别人写好的代码咱们可以直接拿过来使用。
2️⃣把下载好的jar包拷贝到lib目录中
简单的复制粘贴哦
3️⃣右键刚才的lib目录,选择add as library告诉idea这个lib目录是一个“库”目录
添加完"库"之后,此时idea就能自动分析出jar包里都有啥
注意:上述导包的方式是适用于初学者的简单粗暴的方式,实际开发中,一般不会这么搞,有更好的办法。
通过代码使用JDBC的API
(1)创建数据源对象并设置属性
下面要设置的三个属性都是子类具有的,DataSource本身没有相关的方法和属性
DataSource dataSource=new MysqlDataSource();
DataSource是Java标准库JDBC自带的接口,而MysqlDataSource则来自于咱们刚才手动导入的jar包。像如果有一天要操作Oracle就要newOracle数据库提供的具体的对象。
设置三种属性
DataSource dataSource=new MysqlDataSource();
((MysqlDataSource) dataSource).setUrl();
((MysqlDataSource) dataSource).setUser();
((MysqlDataSource) dataSource).setPassword();
第一行代码用到了向上转型,但是为了设置属性又用到了向下转型。有人说这不就画蛇添足了吗?
其实创建数据源还有一种方式
MysqlDataSource dataSource=new MysqlDataSource();
dataSource.setUrl();
dataSource.setUser();
dataSource.setPassword();
那为什么有人就是要用第一种呢?🧐🧐🧐
按照第一种写法,后续代码中如果再使用DataSource这个东西,是看不到"MysqlDataSource"这个信息的,就使得后续的其他部分代码和"mysql"这个概念解耦合了,后面的代码,和啥数据库没关系。如果要更换数据库,此时代码修改的成本就比较低。
实则,实际开发中,"更换数据库"这种事情,本身就属于是非常低频的操作,而且如果真的更换数据库,往往要做很多方面的考量和调整,绝对不是,修改3-4行代码就能轻易完成的,
而且,第一种的代码,其实也付出了代价,为了降低耦合,写了一堆转型,对于代码的可读性是有负面作用的。
总的说来上面两种方式都是可以的,看个人的喜好吧👻👻👻
🔦属性一:数据库服务器在哪里
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/java112characterEncoding=utf8&useSSL=false");
这一串东西不用背,写代码的时候直接复制粘贴即可,我们来了解一下每一部分的内容。😘😘😘
描述了url的用途是给jdbc的mysql来使用的
IP地址.描述了mysql服务器所在的主机的位置,mysql是客户端服务器结构的程序客户端和服务器之间是通过网络来通信的,此时就通过IP地址这样的概念来描述mysql服务器是在哪个主机上。127.0.0.1这个IP是一个特殊的地址表示"你本机",因为咱们JDBC的代码和mysql服务器都是在同一个机器上,此时IP地址就都固定写成127.0.0.1即可。如果是在不同主机上,再写别的地址。
端口号,用来区分一个主机上的应用程序的,比如,我自己这个机器上,就有好多应用程序在使用网络,比如,浏览器,qq音乐,mysql服务器.…后续发来一个网络的数据,是要交给哪个程序来处理呢?就需要通过端口号来区分了。mysql安装时,默认端口号3306(安装有个步骤可以设置端口号,如果你没有设置过就是3306)。
我数据库的名字
额外的参数起到了针对这次的数据库连接,解释说明。useSSL=false是关闭加密,有的同学,环境存在问题,开启加密无法连上数据库。
我再举个例子来让你们理解这一串长长的代码
假设我在某个餐厅盘下一个档口(18号)有同学拿着传单来这边吃饭。
1)餐厅确定位置=>IP地址
2)18号档口=>端口号
3)猪肉的熏肉大饼=>数据库名 访问的资源是哪个
通过后续的查询字符串,?后面的部分做一些补充说明 是否放辣椒/是否放葱/是否放香菜
jdbc:mysql:://陕科大六餐厅:18号/猪肉熏肉大饼?辣椒=微辣&葱=少葱&香菜=要
📽属性二:访问服务器的账户是啥
dataSource.setUser("root");
root是mysql自带的用户,管理员用户,权限是最高的
🏓属性三:访问服务器的密码是啥
dataSource.setPassword("123456");
这里写的密码和你装数据库时设置的密码要一致
(2)和数据库服务器建立网络连接
Connection connection = dataSource.getConnection();
此处的连接类似于“打通电话”的抽象连接📞📞📞,connection对象就表示了这个连接,导包的时候别导错了,导入的是第一个
连接建立成功🎉🎉🎉
注意:连接失败可能是上述设置属性信息时的错误,控制台都会显示异常信息。访问的数据库的IP/端口号/数据库名/相关参数/用户名密码都有可能出错。
在这给大家演示一下🤪🤪🤪
密码错误时
数据库名错误
端口号错误
(3)程序构造SQL语句
构造方式有很多种,这里就介绍一种最主流的基于PreparedStatement这个类的。
PreparedStatement为预编译的语句。正常来说,在cmd敲的sql,是把sql发送到mysql服务器mysq服务器负责解析,解析完成之后,执行。解析检查sql是否有语法错误,具体要完成什么工作。由于mysql服务器,同一时刻可能要同时给多个客户端提供服务,解析工作积少成多,也就会比较消耗资源。因此往往就可以把解析工作,放到客户端来完成(自己写的代码),客户端发送sql之前,先解析好,先把一些能做的工作做好,这样服务器就可以降低一些工作量,减轻压力了。
String sql = "insert into student values(1,'张三')";
PreparedStatement statement = connection.prepareStatement(sql);
Statement对象主要是将SQL语句发送到数据库中。JDBC API中主要提供了三种Statement对象
实际开发中最常用的是PreparedStatement对象,以下对其的总结:
(4)把SQL发送到服务器上进行执行
为了更好的观察我们在MySQL客户端先创建好一个表并插入一条信息
update、insert、delete语句
executeUpdate()方法返回值是一个整数,指示受影响的行数,通常用于update、insert、delete语句。
int n = statement.executeUpdate();
System.out.println(n);
这里的执行是真正和数据库服务器进行网络通信,执行完之后就有了两条张三的信息了
插入数据时能不能由用户自己指定插入的内容呢
Scanner sc = new Scanner(System.in);
System.out.println("请输入id:");
int id = sc.nextInt();
System.out.println("请输入name:");
String name = sc.next();String sql = "insert into student values(" + id + ", '" + name + "')";
PreparedStatement statement = connection.prepareStatement(sql);
这样拼字符串,不太好
1.代码看起来比较乱.容易写错
2.可能会引起"sql"注入攻击,比如有人输入的时候不好好输入,故意使坏,就可能使执行sql的时候,产生一定的"负面影响”
String sql = "insert into student values(? ,?)";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setInt(1, id);
statement.setString(2, name);
使用“?”先占个位置后续再替换掉类似于C的printf的%d一样
删除也是一样的
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;public class Main {public static void main(String[] args) throws SQLException {Scanner sc = new Scanner(System.in);System.out.println("请输入id:");int id = sc.nextInt();
// System.out.println("请输入name:");
// String name = sc.next();MysqlDataSource dataSource = new MysqlDataSource();dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/java112?characterEncoding=utf8&useSSL=false");dataSource.setUser("root");dataSource.setPassword("123456");Connection connection = dataSource.getConnection();String sql = "delete from student where id = ?";PreparedStatement statement = connection.prepareStatement(sql);statement.setInt(1, id);int n = statement.executeUpdate();System.out.println(n);statement.close();connection.close();}
}
select语句
executeQuery() 方法执行后返回单个结果集的集合,通常用于select语句
select操作,和上述操作相比,有所差异,多了一个步骤,"遍历结果集合"。
先往表中插入两行
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class Main {public static void main(String[] args) throws SQLException {MysqlDataSource dataSource = new MysqlDataSource();dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/java112?characterEncoding=utf8&useSSL=false");dataSource.setUser("root");dataSource.setPassword("123456");Connection connection = dataSource.getConnection();String sql = "select * from student";PreparedStatement statement = connection.prepareStatement(sql);ResultSet resultSet = statement.executeQuery();while (resultSet.next()) {System.out.print(resultSet.getInt("id") + " ");System.out.println(resultSet.getString("name"));}resultSet.close();statement.close();connection.close();}
}
ResultSet对象它被称为结果集,它代表符合SQL语句条件的所有行,并且它通过一套getXXX方法提供了对这些行中数据的访问。
ResultSet里的数据一行一行排列,每行有多个字段,并且有一个记录指针,指针所指的数据行叫做当前数据行,我们只能来操作当前的数据行。我们如果想要取得某一条记录,就要使用ResultSet的next()方法 ,类似于迭代器操作,如果我们想要得到ResultSet里的所有记录,就应该使用while循环。
(5)释放资源
释放资源的顺序要和创建资源的顺序相反。建立连接/创建语句的时候就需要消耗一定的内存/硬盘/网络等资源这些资源,都是跟随这个连接来走的.如果连接不再使用了,就需要把这些资源释放掉.
🥘如果执行的是update、insert、delete语句
statement.close();
connection.close();
🍛如果执行的是select语句
resultSet.close();
statement.close();
connection.close();
JDBC实际开发中,一般不会直接使用,这个东西的代码,写起来比较麻烦,后来就有了很多的库和框架,来针对JDBC进行封装和简化(都是基于JDBC),后续学习MyBaits框架,就属于是针对JDBC简化后的组件。所谓的框架,说到底,都是别人,针对一些"通用场景"开发出来的程序组件。未来实际开发中,很可能会遇到一些"特定场景”,此时,通用的框架,可能就会失效就需要咱们有能力对已有框架进行魔改,魔改成能适应特定场景/或者能自己造出适合的框架…...