1、JDBC的概念
讲解
客户端操作MySQL数据库的方式
- 使用第三方客户端来访问MySQL:SQLyog、Navicat
- 使用MySQL自带的命令行方式
- 通过Java来访问MySQL数据库,今天要学习的内容
如何通过Java代码去操作数据库呢?
Java中给我们提供专门的一套技术,可以通过其中的某些类和接口操作任何的数据库,这个技术就是今天要学习的JDBC。
什么是JDBC:Sun公司为了简化、统一对数据库的操作,定义了一套java操作数据库的接口的规范,称之为JDBC。JDBC的全称为:java database connection (java和 数据库的连接 ) 就是使用java代码来操作数据库。
JDBC的作用:Java通过JDBC就可以操作数据库
JDBC的由来
- java程序依赖于jdk,jdk和数据库是2个不同的应用程序,那他们是怎么进行访问的呢?
要想搞清楚这个问题,我们必须了解下电脑是如何和其他硬件设备交互的。假设我们电脑安装完系统之后是一个无驱动的操作系统。那么当我们电脑想播放声音,即安装音响,必须得安装声卡驱动。同时电脑想和u盘硬件进行交互,也必须在电脑上安装对应的驱动。如果驱动安装失败,很显然他们是不能正常的交互的。这个安装驱动的其实就是为了定义他们两个相互交互的规则。只有统一了规则,才能交互。
具体的解释如下图所示:
同理:java程序想和数据库进行交互,也必须得安装数据库驱动,这样才能交互。但是,我们数据库有多种,这样就会导致不同的数据库具备不同的数据库驱动。
从而会导致在开发中作为程序员由于安装不同的数据库驱动而浪费很多时间,同时和数据库交互的java代码也得重新书写,这样都会导致效率很低。所以说,sun公司就会制定一套规则,这套规则就是用来java程序连接数据库的,然后各大数据库厂商只需要实现这个规则即可。这个规则就是jdbc技术,即接口。
换句话就是说,就是数据库厂商使用sun公司提供的接口,然后作为java程序员实现接口中的方法即可。接口中的方法体由具体的数据库厂商来实现。
JDBC的好处
- 我们只需要会调用JDBC接口中的方法即可,使用简单
- JDBC有关的类和接口:都在java.sql 和 javax.sql(扩展包) 包下
- 方法体由具体的数据库厂商来完成的
- 使用同一套Java代码,进行少量的修改就可以访问其他JDBC支持的数据库
2、JDBC核心API的介绍
讲解
JDBC会用到的包
- java.sql:JDBC访问数据库的基础包,在JavaSE中的包。如:
java.sql.Connection
- javax.sql: JDBC访问数据库的扩展包
- 数据库的驱动,各大数据库厂商来实现。如:MySQL的驱动:
com.mysql.jdbc.Driver
JDBC四个核心对象
这几个类都是在java.sql包中
- DriverManager(类): 数据库驱动管理类。这个类的作用:1)注册驱动; 2)创建java代码和数据库之间的连接,即获取Connection接口;
- Connection(接口): 是一个接口, 建立数据库连接的一个接口。作用:建立数据库和java代码之间的连接。表示与数据库创建的连接
- Statement(接口)、PreparedStatement(接口) (解决安全隐患问题,比如sql注入的问题): 数据库操作,向数据库发送sql语句。执行SQL语句的对象
- ResultSet: 结果集或一张虚拟表。 Statement 发送sql语句,得到的结果 封装在 ResultSet 中。
JDBC访问数据库的步骤
- 由DriverManager注册驱动程序
- 创建和数据库的连接对象Connection
- 由客户端发送SQL语句给服务器执行,SQL语句封装成Statement对象
- 查询到的结果集封装成ResultSet对象
- 在客户端可以从ResultSet中取出数据,处理结果集
- 释放资源,关闭连接对象
小结
JDBC四个核心对象?
- DriverManager(类): 用于注册驱动和获取连接
- Connection(接口): 表示与数据库创建的连接
- Statement(接口): 执行SQL语句的对象
- ResultSet(接口): 结果集或一张虚拟表
3、JDBC注册驱动
Connection
表示Java程序与数据库之间的连接,只有拿到Connection才能操作数据库。
JDBC获取连接步骤
1.导入mysql驱动Jar包
2.注册驱动
3.获取连接
讲解
准备工作
1、确定启动mysql数据库。
2、创建数据库和创建user表,并添加信息,sql语句如下。
打开可视化工具,将如下sql语句添加到可视化工具中,并执行以下sql语句即可。
-- 创建数据库 create database day04_db; -- 切换数据库 use day04_db; -- 用户表 create table user ( id int primary key auto_increment, username varchar(30) unique not null, password varchar(30) ); insert into user(username, password) values('zhangsan','123'); insert into user(username, password) values('lisi','123'); insert into user(username, password) values('wangwu','123'); select * from user;
执行结果:
导入驱动Jar包
1、新建项目day04,在项目day04上新建lib文件夹
2、将mysql驱动的jar包导入到lib文件夹下
3、在导入的mysql的jar包上右键,选择Add as Library…
注册驱动
我们Java程序需要通过数据库驱动才能连接到数据库,因此需要注册驱动。
MySQL的驱动的入口类是:com.mysql.jdbc.Driver
API介绍
java.sql.DriverManager
类用于注册驱动。提供如下方法注册驱动
static void registerDriver(Driver driver) 向 DriverManager 注册给定驱动程序。
说明:
1)执行完上述语句之后,DriverManager就可以管理mysql驱动了。
2)当前的DriverManager.registerDriver(Driver driver);方法的参数是Driver,这是jdbc的一个接口,所以我们需要给定实现该接口的实现类。如果我们连接的是mysql数据库,那么需要导入mysql数据库提供的包,也就是com.mysql.jdbc.Driver; 下的Driver类。如果我们连接的是oracle数据库,那么需要导入oracle数据库提供的包。
使用步骤
1.DriverManager.registerDriver(驱动对象); 传入对应参数即可
案例代码
public class Demo01 { public static void main(String[] args) throws Exception { // 注册驱动 DriverManager.registerDriver(new com.mysql.jdbc.Driver()); } }
说明:这里的new Driver()的类Driver就是来自mysql数据库。
通过查询com.mysql.jdbc.Driver源码,我们发现Driver类“主动”将自己进行注册
public class Driver extends NonRegisteringDriver implements java.sql.Driver { static { try { // 自己自动注册 java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } public Driver() throws SQLException { } }
注意:使用
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
,存在以下方面不足
- 驱动被注册两次
使用Class.forName("com.mysql.jdbc.Driver");
加载驱动,这样驱动只会注册一次
public class Demo01 { public static void main(String[] args) throws Exception { /* 1)注册驱动使用的类是驱动管理类:DriverManager,使用该类中的静态方法: static void registerDriver(Driver driver) 向 DriverManager 注册给定驱动程序。 真正注册驱动代码: DriverManager.registerDriver(new Driver()); 2) static void registerDriver(Driver driver) 方法参数Driver是驱动接口,java.sql.Driver表示每个驱动程序类必须实现的接口。 对于该参数我们都是创建该接口java.sql.Driver实现类对象,实现类由各大数据库厂商来提供,并且必须实现该驱动接口java.sql.Driver 3) 真正注册驱动代码: DriverManager.registerDriver(new Driver()); 注意:这里new Driver()创建的是mysql厂商定义的实现类 //com.mysql.jdbc.Driver 属于mysql厂商的实现类 //java.sql.Driver 属于sun公司定义的驱动接口 public class com.mysql.jdbc.Driver implements java.sql.Driver { public Driver() throws SQLException { } static { try { DriverManager.registerDriver(new Driver()); } catch (SQLException var1) { throw new RuntimeException("Can't register driver!"); } } } 4)为什么我们不使用代码: DriverManager.registerDriver(new Driver()); 注册呢,我们为什么这里使用代码: Class.forName("com.mysql.jdbc.Driver");的原因? 原因:因为DriverManager.registerDriver(new Driver());注册了两次,而Class.forName("com.mysql.jdbc.Driver");只是注册了一次 Class.forName("com.mysql.jdbc.Driver"); 就是将com.mysql.jdbc.Driver类加载到内存中,加载该类,就会执行该类的静态代码块: public class com.mysql.jdbc.Driver implements java.sql.Driver { //静态代码块,当前类一加载内存就执行 static { try { //注册驱动的真正代码 DriverManager.registerDriver(new Driver()); } catch (SQLException var1) { throw new RuntimeException("Can't register driver!"); } } } 总结: Class.forName("com.mysql.jdbc.Driver");注册一次驱动原因,类com.mysql.jdbc.Driver加载内存中执行静态代码块 然后注册驱动了 5)为什么 我们自己书写该代码DriverManager.registerDriver(new Driver()); 注册两次? 因为首先在执行代码:new com.mysql.jdbc.Driver() ,先将类com.mysql.jdbc.Driver加载到内存中执行静态代码块,注册一次驱动,然后 这里又注册一次 6)从jdbc4开始,我们第一步注册驱动不用我们程序员书写了,,底层在使用到com.mysql.jdbc.Driver类就注册了 */ Class.forName("com.mysql.jdbc.Driver"); // 后期可以将"com.mysql.jdbc.Driver"字符串写在文件中. } }
演示:Class.forName("包名.类名");
会走这个类的静态代码块
通常开发我们使用Class.forName() 加载驱动。Class.forName("com.mysql.jdbc.Driver");
会走Driver类的静态代码块。在静态代码块中注册一次驱动。
总结:注册MySQL驱动使用
Class.forName("com.mysql.jdbc.Driver");
小结
- 导入mysql驱动Jar包
- 通过JDBC注册数据库驱动?
Class.forName("com.mysql.jdbc.Driver"); • 1
- 3.从jdk4.0开始,对于我们java开发工程师,第一步不用书写了,底层帮助我们使用com.mysql.jdbc.Driver类先注册驱动了.
驱动必须注册,只是不用我们书写代码注册了。
4、获取连接
讲解
API介绍
java.sql.DriverManager
类中有如下方法获取数据库连接
static Connection getConnection(String url, String user, String password) 连接到给定数据库 URL ,并返回连接。
参数说明
String url
:连接数据库的URL,用于说明连接数据库的位置String user
:数据库的账号String password
:数据库的密码
连接数据库的URL地址格式:协议名:子协议://服务器名或IP地址:端口号/数据库名?参数=参数值
MySQL写法:jdbc:mysql://localhost:3306/day04_db
如果是本地服务器,端口号是默认的3306,则可以简写:jdbc:mysql:///day04_db
注意事项
如果数据出现乱码需要加上参数: ?useUnicode=true&characterEncoding=utf8,表示让数据库以UTF8编码来处理数据。
如: jdbc:mysql://localhost:3306/day04_db?useUnicode=true&characterEncoding=utf8
使用步骤
1.DriverManager.getConnection(url, user, password); 传入对应参数即可
案例代码
public class Demo01 { public static void main(String[] args) throws Exception { Class.forName("com.mysql.jdbc.Driver"); /* 1)使用DriverManager类中的静态方法获取和数据库的连接: static Connection getConnection(String url, String user, String password) 参数: url:表示建立和数据库服务器连接的地址,书写格式几乎是固定的。 jdbc:mysql://连接mysql服务器的ip地址:mysql服务器的端口号/连接的数据库名 补充:如果连接的数据库软件在本地,那么url可以简写为:jdbc:mysql:///连接的数据库名 user:连接mysql服务器的用户名,这里暂时书写root password:接mysql服务器的密码 返回值:Connection,属于java.sql 包下的一个接口,表示连接接口,和数据库的连接。 */ // 连接到MySQL // url: 连接数据库的URL // user: 数据库的账号 // password: 数据库的密码 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day04_db", "root", "1234"); System.out.println(conn); } }
案例效果
1.连接成功
2.连接失败
小结
- JDBC获取数据库连接使用哪个API?
DriverManager.getConnection(数据库url, 账号, 密码)
- 通过JDBC连接mysql的URL写法?
jdbc:mysql://服务器ip地址:3306/数据库
3.如果连接mysql服务器在本地,那么url可以简写:
jdbc:mysql:///数据库
5、JDBC实现对单表数据增、删、改
讲解
JDBC实现对单表数据增、删、改
我们要对数据库进行增、删、改、查,需要使用Statement
对象来执行SQL语句。
API介绍
获取Statement对象
在java.sql.Connection
接口中有如下方法获取到Statement
对象
Statement createStatement() 创建一个 Statement 对象来将 SQL 语句发送到数据库
Statement的API介绍
int executeUpdate(String sql) 根据执行的DML(INSERT、UPDATE、DELETE)语句,返回受影响的行数
ResultSet executeQuery(String sql) 根据查询语句返回结果集,只能执行SELECT语句
注意:在MySQL中,只要不是查询就是修改。
executeUpdate:用于执行增删改
executeQuery:用于执行查询
使用步骤
- 注册驱动
- 获取连接
- 获取Statement对象
- 使用Statement对象执行SQL语句
- 释放资源
案例代码
public class Demo03 { public static void main(String[] args) throws Exception { Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql:///day04_db", "root", "1234"); System.out.println(conn); /* 1)获取发送sql语句对象使用Connection连接接口对象调用Connection接口的方法: Statement createStatement() 创建一个 Statement 对象来将 SQL 语句发送到数据库。 PreparedStatement prepareStatement(String sql) 创建一个 PreparedStatement 对象来将参数化的 SQL 语句发送到数据库。 2)Statement和PreparedStatement都可以用来向数据库发送sql语句,Statement是PreparedStatement的父接口。 3)PreparedStatement 是安全的,Statement不安全的。并且Statement效率低,PreparedStatement效率高 4)Connection还可以手动控制mysql事务: 开启事务 void setAutoCommit(boolean autoCommit) 将此连接的自动提交模式设置为给定状态。 autoCommit - 为 true 表示启用自动提交模式;为 false 表示禁用自动提交模式 1. conn.setAutoCommit(false); 一切正常提交事务 void commit() 2. conn.commit() 出现异常,回滚事务 void rollback() 3. conn.rollback() */ // 从连接中拿到一个Statement对象 Statement stmt = conn.createStatement(); /* Statement向数据库发送sql语句,使用Statement中的不同的方法可以向数据库发送不同的sql语句: 1)DQL查询语句: ResultSet executeQuery(String sql) 执行给定的 SQL 语句,该语句返回单个 ResultSet 对象。 参数:sql - 要发送给数据库的 SQL 语句,通常为静态 SQL SELECT 语句 返回值:ResultSet用来存放查询的结果,表示结果集 2)DML增删改和DDL语句(创建表和数据库)使用的方法: int executeUpdate(String sql) 执行给定 SQL 语句,该语句可能为 INSERT、UPDATE 或 DELETE 语句(DML), 或者不返回任何内容的 SQL 语句(如 SQL DDL 语句)。 返回值: 1) 对于 SQL 数据操作语言 (DML) 语句,返回行记录数,影响的行数 2) 对于什么都不返回的 SQL 语句,返回 0 ,执行DDL返回的是0 了解 */ // 1.插入记录 String sql = "insert into user values(null, 'zhaoliu', 'abc')"; int i = stmt.executeUpdate(sql); System.out.println("影响的行数:" + i); // 2.修改记录 sql = "update user set username='tianqi' where username='zhaoliu'"; i = stmt.executeUpdate(sql); System.out.println("影响的行数:" + i); // 3.删除记录 sql = "delete from user where id=4"; i = stmt.executeUpdate(sql); System.out.println("影响的行数:" + i); // 释放资源 stmt.close(); conn.close(); } }
6、JDBC实现对单表数据查询
讲解
ResultSet
用于保存执行查询SQL语句的结果。
我们不能一次性取出所有的数据,需要一行一行的取出。
ResultSet的原理
- ResultSet内部有一个指针,刚开始记录开始位置
- 调用next方法, ResultSet内部指针会移动到下一行数据
- 我们可以通过ResultSet得到一行数据 getXxx得到某列数据
ResultSet获取数据的API
其实ResultSet获取数据的API是有规律的get后面加数据类型。我们统称getXXX()
例如:
对于上图中的一行数据,我要获取username为zhangsan这列的值,有如下2种写法:
- rs.getString(“username”); 通过列名获取该列的值。
- rs.getString(2); 通过username列所在的第二个位置获取该列的值。
使用JDBC查询数据库中的数据的步骤
- 注册驱动
- 获取连接
- 获取到Statement
- 使用Statement执行SQL
- ResultSet处理结果
- 关闭资源
案例代码
public class Demo04 { public static void main(String[] args) throws Exception { Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql:///day04_db", "root", "1234"); Statement stmt = conn.createStatement(); String sql = "select * from user"; ResultSet rs = stmt.executeQuery(sql); // 内部有一个指针,只能取指针指向的那条记录 while(rs.next()){// 指针移动一行,有数据才返回true int id = rs.getInt("id"); String name = rs.getString(2); String pwd= rs.getString(3); System.out.println(id+"+++"+name+"++++"+pwd); } // 关闭资源 rs.close(); stmt.close(); conn.close(); } }
小结
其实我们使用JDBC操作数据库的步骤都是固定的。不同的地方是在编写SQL语句
- 注册驱动
- 获取连接
- 获取到Statement
- 使用Statement执行SQL
- ResultSet处理结果
- 关闭资源
ResultSet如何获取数据?
- 调用next方法, ResultSet内部指针会移动到下一行数据
- 我们可以通过ResultSet得到一行数据 getXxx得到某列数据
JDBC是真的啰里啰嗦啊-但是很重要!(下):