Mysql版本:8.0.26
可视化客户端:sql yog
编译软件:IntelliJ IDEA 2019.2.4 x64
运行环境:win10 家庭中文版
jdk版本:1.8.0_361
前言
随着人工智能与大数据的不断发展,数据库管理与运维这门技术也越来越重要,很多人都开启了学习此项技能的脚步,对于开发者来说,尤其是涉及程序与数据库的数据交互,更是重要,本文带你介绍Java程序与MySQL数据库之间的信息交互的“那些事”。
提示:以下是本篇文章正文内容,下面案例可供参考
一、JDBC是什么?
JDBC,全称Java Database Connectivity,用官方一点的说法解释是:
它代表一组独立于任何数据库管理系统(DBMS)的API,声明在java.sql与javax.sql包中,是SUN(现在Oracle)提供的一组接口规范。由各个数据库厂商来提供实现类,这些实现类的集合构成了数据库驱动jar。
👉用通俗的话来讲:
JDBC就是Java程序用来连接各种数据库的API。 该API是由上述的SUN(Oracle)提供的一组公共接口+各个数据库厂商提供的驱动类构成。
JDBC API的构成关系如下图所示:
二、如何使用JDBC连接数据库?
👉备注:本文以
MySQL数据库
作为案例
2.1 引入mysql驱动jar包
方式一:单独某个模块使用mysql驱动
👉步骤:
👉①在你的Java项目目录下新建一个名为“jdbclibs”的文件夹,将下载好的jar包复制粘贴到刚才新建的“jdbclibs”的文件夹中。
ps:相关jar包资源我会上传至c站资源
👉②打开你的IDEA,找到下面的图标,点击打开,随后呈现的是“
project structure
”选项卡。
👉③在
project structure
选项卡中,libraries -> + -> java -> select libraries file -> 选中刚才新建的jdbclibs文件夹
👉 ④在
choose Modules
选项卡选中你要应用的模块,然后点击“ok”
👉⑤为单模块添加mysql驱动已完成
方式二:为整个项目使用mysql驱动
👉 ①打开IDEA,找到如下DE1图标,点击打开,随后呈现的是“
project structure
”选项卡。
👉 ②在
project structure
选项卡中,Modules -> 选中所有的模块 -> + -> library
👉③在
chose libraries
界面 选中刚才新加的jdbclibs1 jar包,选择“add selected
”
👉④选中后,在“
dependence
”下将新加入的jdbclibs1的scope范围切换为“Compile
”,最后点击“ok
”完成。
方式三:使用maven
ps:此方法留作后期叙述
2.2 Java程序连接数据库
👉步骤:
1、模块添加了依赖的mysql驱动相关库
注意:我们在2.1中执行的操作就是给Java项目添加需依赖的mysql驱动
2、在内存中加载驱动类(可选)
- 更早版本mysql驱动类:
org.gjt.mm.mysql.Driver
- 最近版本:
com.mysql.jdbc.Driver
- MySQL8.0版本:
com.mysql.cj.jdbc.Driver
👉注意:
如果你的jar包是旧版的,你必须在主方法中首行写下如下的代码,手动加载对应的的驱动类。
代码如下:
Class.forName("com.mysql.cj.jdbc.Driver");
新版的mysql驱动jar可以省略这步,旧版的mysql驱动jar必须加这一步。
👉why?
因为新版mysql驱动jar包下有一个META-INF/services/java.sql.Driver文件
里面有填写mysql驱动类的全名称,DriverManager会自动读取这个文件,并加载对应的驱动类
如下图所示:
👉小tips:
我们在后期使用数据库连接池,或者MyBatis等框架时,在配置文件中需要加这个驱动类的配置
3、连接数据库:通过DriverManager工具类获取数据库连接Connection的对象
。
此时Java程序是MySQL的一个客户端
👉连接数据库需要如下参数:
MySQL服务器主机的IP地址
端口号
用户名
密码
要连接的数据库名称
(这一点和使用命令行客户端、可视化工具客户端不一样),一个连接只能查看一个数据库
👉 如何把这些信息告诉给驱动类的底层呢?
通过url 传给底层,url是字符串类型,它将下面的内容包成字符串传给底层,使其构建连接
协议://主机名: 端口号/数据库名?参数名=套数值
协议是什么?
如我们司空见惯的网址,例如百度的网址http://www.baidu.com,它采用的就是http协议。
👉而Java程序连接数据库却是采用jdbc协议
👉
jdbc:mysql://localhost:3306/0106db
👉备注:
jdbc是主协议,mysql是子协议,localhost表示连接本机的mysgl数据库,3306是端口号,0106db是一个数据库名
案例:连接数据库0106db
代码演示如下:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class testJdbc { //DriverManager: 驱动管理 //getConnection: 获取连接 /* A: 提供mysql服务所在主机的IP地址或主机名 B: 端口号 C: 用户名 D: 密码 E: 要连接的数据库名称(这一点和使用命令行客户端、可视化工具客户端不一样),一个连接只能查看一个数据库 如何把这些信息告诉底层呢? 通过url 协议://主机名: 口号/数据库名?参数名=套数值 http://www.atquigu.com jdbc:mysql://localhost:3306/0106db jidbc是主协议,mysql是子协议,localhost表示连接本机的mysgl数据库,3306是端口号,atguigu是一个数据库名 */ public static void main(String[] args) throws SQLException { //Class.forName("com.mysql.cj.jdbc.Driver"),如果在web阶段学习时,Tomcat服务器提示找不到合适的驱动类,但是代码都是对的,可以自己手动加载一下 Connection root = DriverManager.getConnection(url, "root", "123456"); System.out.println(root); root.close();//断开连接并释放资源 } }
原因分析: 当我们的数据库版本是MySQL8.0及以上时,url需要加参数,即serverTimezone=UTC
,否则会上述报错
代码修正如下:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class testJdbc { //DriverManager: 驱动管理 //getConnection: 获取连接 /* A: 提供mysql服务所在主机的IP地址或主机名 B: 端口号 C: 用户名 D: 密码 E: 要连接的数据库名称(这一点和使用命令行客户端、可视化工具客户端不一样),一个连接只能查看一个数据库 如何把这些信息告诉底层呢? 通过url 协议://主机名: 口号/数据库名?参数名=套数值 http://www.atquigu.com jdbc:mysql://localhost:3306/0106db jidbc是主协议,mysql是子协议,localhost表示连接本机的mysgl数据库,3306是端口号,atguigu是一个数据库名 */ public static void main(String[] args) throws SQLException { //Class.forName("com.mysql.cj.jdbc.Driver"),如果在web阶段学习时,Tomcat服务器提示找不到合适的驱动类,但是代码都是对的,可以自己手动加载一下 // String url="jdbc:mysql://localhost:3306/0106db"; /* 如果不加?serverTimezone=UTC 会报如下异常: Excepton in thread "main" java.sql.SQLException: The server time zone value '�й���ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use a more specifc time zone value if you want to utilize time zone support. */ //修正如下: String url="jdbc:mysql://localhost:3306/0106db?serverTimezone=UTC"; Connection root = DriverManager.getConnection(url, "root", "123456");//开始连接数据库,相当于网络编程中的socket System.out.println(root);//打印连接对象 root.close();//断开连接并释放资源 } }
4、断开连接:使用close方法。
代码如下所示:
root.close();//断开连接并释放资源
三、连接数据库后,JDBC如何实现增删改查?
3.1 JDBC实现插入数据
👉步骤:
- 连接数据库获取Connection对象 ==>(相当于) Socket
- 编写insert的sql语句
- 获取一个Preparedstatement对象 ==>(相当于) 输出流/输入流
- 使用Preparedstatement对象执行sql语句
👉注意:
只要是修改数据库的数据(添加、删除、修改) ,调用的方法都是 executeUpdate()
- 释放资源
案例:使用jdbc连接数据库0225db,在t_deployment表中插入一条数据
插入之前:
代码插入如下:
//jdbc实现插入数据 import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; public class testInsert { public static void main(String[] args) throws SQLException { //开始连接数据库,相当于网络编程中的socket String url="jdbc:mysql://localhost:3306/0225db?serverTimezone=UTC"; Connection root = DriverManager.getConnection(url, "root", "123456"); String sql="INSERT INTO t_department VALUES(7,'保安部','负责安保巡逻工作')"; PreparedStatement pst = root.prepareStatement(sql);//把sql语句装进去;相当于通过PreparedStatement对象把sql发送给MySQL服务端 int len=pst.executeUpdate();//len代表的是影响的记录数,真正发送数据的是pst.executeUpdate() /* int len = pst.executeUpdate() 执行操作增删改,并返回一个int型数值,表示同步更新的记录条数 */ System.out.println(len>0?"添加成功":"添加失败"); //释放资源 pst.close(); root.close(); } }
3.2 JDBC实现删除数据
👉步骤:
- 连接数据库获取Connection对象 ==>(相当于) Socket
- 编写delete的sql语句
- 获取一个Preparedstatement对象 ==>(相当于) 输出流/输入流
- 使用Preparedstatement对象执行sql语句
👉注意:
只要是修改数据库的数据(添加、删除、修改) ,调用的方法都是 executeUpdate()
- 释放资源
案例:使用jdbc连接数据库0225db,在t_deployment表中删除刚才插入的一条数据
删除之前:
代码删除如下:
//jdbc实现删除数据 import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; public class testDelete { public static void main(String[] args) throws SQLException { //开始连接本机的MySQL服务端 String url="jdbc:mysql://localhost:3306/0225db?serverTimezone=UTC"; Connection root = DriverManager.getConnection(url, "root", "123456"); String sql="delete from t_department where did=7"; PreparedStatement pst = root.prepareStatement(sql);//把sql语句装进PreparedStatement对象中,准备发送 int len = pst.executeUpdate();//真正发送sql语句 /* int len = pst.executeUpdate() 执行操作增删改,并返回一个int型数值,表示同步更新的记录条数 */ System.out.println(len>0?"删除成功":"删除失败"); //释放资源 pst.close(); root.close(); } }
3.3 JDBC实现修改数据
👉步骤:
- 连接数据库获取Connection对象 ==>(相当于) Socket
- 编写update的sql语句
- 获取一个Preparedstatement对象 ==>(相当于) 输出流/输入流
- 使用Preparedstatement对象执行sql语句
👉注意:
只要是修改数据库的数据(添加、删除、修改) ,调用的方法都是 executeUpdate()
- 释放资源
案例:使用jdbc连接数据库,将did为7的dname的值改为安保部
修改之前:
代码修改如下:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; //jdbc实现更新数据 public class testUpdate { public static void main(String[] args) throws SQLException { //开始连接本机的MySQL服务端 String url="jdbc:mysql://localhost:3306/0225db?serverTimezone=UTC"; Connection root = DriverManager.getConnection(url, "root", "123456"); String sql="UPDATE t_department SET dname='安保部' WHERE did=7"; PreparedStatement pst = root.prepareStatement(sql);//把sql语句装进PreparedStatement对象中,准备发送 int len = pst.executeUpdate();//真正发送sql语句 /* int len = pst.executeUpdate() 执行操作增删改,并返回一个int型数值,表示同步更新的记录条数 */ System.out.println(len>0?"更新成功":"更新失败"); //释放资源 pst.close(); root.close(); } }
3.4 JDBC实现查询数据
👉步骤:
- 连接数据库获取Connection对象 ==>(相当于) Socket
- 编写select的sql语句
- 获取一个Preparedstatement对象 ==>(相当于) 输出流/输入流
- 使用Preparedstatement对象执行sql语句
👉注意:
只要是修改数据库的数据(添加、删除、修改) ,调用的方法都是 executeUpdate()
执行查询数据库的数据,调用的方法是executeQuery(),它的返回值类型ResultSet结果集
- 遍历结果集
while(rs.next()){ //遍历结果集的每一行 变量=rs.getXXX(字段名/字段列表) }
- 释放资源
案例:使用jdbc连接数据库,查询t_employee表中的所有信息
查询之前:
代码查询如下:
import java.sql.*; //jdbc实现查询数据 public class testSelect { public static void main(String[] args) throws SQLException { //开始连接本机的MySQL服务端 String url="jdbc:mysql://localhost:3306/0225db?serverTimezone=UTC"; Connection root = DriverManager.getConnection(url, "root", "123456"); String sql="select * from t_department"; PreparedStatement pst = root.prepareStatement(sql);//把sql语句装进PreparedStatement对象中,准备发送 ResultSet resultSet = pst.executeQuery();//返回一个结果集;真正发送sql /* //如果查询之前我很清楚表中字段的数据类型,就可以使用如下代码 while (resultSet.next()){ //相当于Collection系列集合得到的iterator迭代器的hashnext()方法 int did=resultSet.getInt("did");//"did"是数据库0225db下t_department表的字段名did String dname=resultSet.getString("dname");//数据库中的字段名 String description=resultSet.getString("description");//数据库中的字段名 System.out.println(did+"\t"+dname+"\t"+description+"\t"); } */ //如果我不是很清楚表中字段的数据类型,使用下列的代码写法,这样做是为了屏蔽数据库字段的数据类型的差异 while (resultSet.next()){ //相当于Collection系列集合得到的iterator迭代器的hashnext()方法 Object did=resultSet.getObject(1);//数据库0225db下t_department表的字段的序号为1 Object dname=resultSet.getObject(2);//数据库中的字段序号为2 Object description=resultSet.getObject(3);//数据库中的字段序号为3 System.out.println(did+"\t"+dname+"\t"+description+"\t"); } //释放资源 resultSet.close(); pst.close(); root.close(); } }