1、JDBC是什么?
Java DataBase Connectivity(Java语言连接数据库)
2、JDBC的本质是什么?
JDBC是SUN公司制定的一套接口(interface)
java.sql.*; (这个软件包下有很多接口。) --》自己查看JDK文档
接口都有调用者和实现者。
面向接口调用、面向接口写实现类,这都属于面向接口编程。
为什么要面向接口编程?
解耦合:降低程序的耦合度,提高程序的扩展力。
多态机制就是非常典型的:面向抽象编程。(不要面向具体编程)
建议:
Animal a = new Cat();
Animal a = new Dog();
// 喂养的方法
public void feed(Animal a){ // 面向父类型编程。
}
不建议:
Dog d = new Dog();
Cat c = new Cat();
public void feed(Dog a){ // 面向父类型编程。
// 那么他就只能处理 Dog类的对象了。!!!
}
思考:为什么SUN制定一套JDBC接口呢?
因为每一个数据库的底层实现原理都不一样。
Oracle数据库有自己的原理。
MySQL数据库也有自己的原理。
MS SqlServer数据库也有自己的原理。
....
每一个数据库产品都有自己独特的实现原理。
总结:JDBC的本质到底是什么?: 一套接口。
3,JDBC本质(接口)的模拟实现
关于JDBC接口应该涉及三类角色:JDBC接口的制定者(SUM公司)、JDBC接口的实现(各数据库公司)和 JDBC调用者(Java程序员,仅需面向接口编程,不必管接口的实现类)
代码模拟:角色1,JDBC接口的制定者(SUM公司)
/*
SUM公司:制定这套JDBC接口
*/
public interface JDBC{
/*
连接数据库的方法
*/
void getConnection();
}
代码模拟:角色2,JDBC接口的现实者(各数据库公司)如MySQL、Oracle、SqlServer。各自针对SUM公司制定的JDBC接口 --》实现自己的JDBC实现类。
/*
MYSQL数据库厂家负责实现编写JDBC接口的实现类
*/
public class MySQL implements JDBC{
public void getConnection(){
// 具体这里的代码怎么写 对于我们java程序员来说没有关系
// 这段代码涉及到mysql底层数据库的实现原理
System.out.println("连接MYSQL数据库成功");
}
}
/*
Oracle数据库厂家负责实现编写JDBC接口的实现类
*/
public class Oracle implements JDBC{
public void getConnection(){
// 具体这里的代码怎么写 对于我们java程序员来说没有关系
// 这段代码涉及到Oracle底层数据库的实现原理
System.out.println("连接Oracle数据库成功");
}
}
/*
SqlServer数据库厂家负责实现编写JDBC接口的实现类
*/
public class SqlServer implements JDBC{
public void getConnection(){
// 具体这里的代码怎么写 对于我们java程序员来说没有关系
// 这段代码涉及到sqlserver底层数据库的实现原理
System.out.println("连接sqlserver数据库成功");
}
}
// 实现类称为驱动 (sqlserver驱动) xxx.class --》 xxx.jar(当中有很多.calss文件,都是对JDBC接口进行实现)。
代码模拟:角色3,JDBC接口的调用者(Java程序员)。仅面对SUM公司提供的JDBC接口进行编程即可,不需要考虑各个数据库产品对于JDBC接口的实现。
/*
Java程序员角色
不需要关心具体是那个数据库产品,只需要面向JDBC接口进行写代码
面向接口编程,面向接口编程, 面向接口编程!!!
*/
import java.util.*;
public class JavaProgrammer{
public static void main(String[] args) throws Exception{
// 创建 JDBC对象
//JDBC jdbc = new MySQL();
// JDBC jdbc = new Oracle();
// 优化创建对象 使用反射机制
// Class c = Class.forName("SqlServer");
// JDBC jdbc = (JDBC)c.newInstance(); // 因为 MySQL Oracle SqlServer 实现了JDBC接口(JDBC是一个父亲),所以可以强转
// 继续优化 创建了配置文件 jdbc.properties文件
ResourceBundle bundle = ResourceBundle.getBundle("jdbc"); // 需要导包 import java.util.*;
String className = bundle.getString("className");
Class c = Class.forName(className);
JDBC jdbc = (JDBC)c.newInstance(); // 这里是创建了一个 className的实现类对象(只是用父对象接受)
// 以下代码都是面向接口调用方法,进行编程
jdbc.getConnection();
}
}
// 实现类称为驱动 (sqlserver驱动) xxx.class --》 xxx.jar(当中有很多.calss文件,都是对JDBC接口进行实现)。
运行结果:
4、JDBC开发前的准备工作
先从官网下载对应的驱动jar包,然后将其配置到环境变量classpath当中。
classpath=.;D:\course\06-JDBC\resources\MySql Connector Java 5.1.23\mysql-connector-java-5.1.23-bin.jar
注意:以上的配置是针对于文本编辑器的方式开发,使用IDEA工具的时候,不需要配置以上的环境变量。 IDEA有自己的配置方式。
5、JDBC编程六步(需要背会)
第一步:注册驱动(作用:告诉Java程序,即将要连接的是哪个品牌的数据库)
第二步:获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,重量级的,使用完之后一定要关闭通道。)
第三步:获取数据库操作对象(专门执行sql语句的对象)
第四步:执行SQL语句(DQL DML....)
第五步:处理查询结果集(只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集。)
第六步:释放资源(使用完资源之后一定要关闭资源。Java和数据库属于进程间的通信,开启之后一定要关闭。)
6,实操 JDBC编程六步法 -- Insert / Update / delete
查看JDK文档:搜索DriverManager
查看JDK文档:搜索Connection
查看JDK文档:搜索Statement
1,注册驱动 DriverManager class中的 getDriver方法 static Driver getDriver(String url) 尝试查找能够理解给定 URL 的驱动程序。 2,获取连接 DriverManager class中的 getConnection方法 static Connection getConnection(String url) 尝试建立与给定数据库 URL 的连接。 static Connection getConnection(String url, String user, String password) 尝试建立与给定数据库 URL 的连接。 static Connection getConnection(String url, Properties info) 尝试建立与给定数据库 URL 的连接。
url:统一资源定位符(网络中某个资源的绝对路径)
https://www.baidu.com/ 这就是一个url
eg:
D:\CScode\MySQL\JDBC>ping www.baidu.com
正在 Ping www.baidu.com [182.61.200.7] 具有 32 字节的数据:
来自 182.61.200.7 的回复: 字节=32 时间=22ms TTL=50
url包括什么:https://182.61.200.7:80/index.html
协议:htpps(通信协议)
IP:182.61.200.7(服务器IP)
端口:80(服务器上软件的端口)
资源名:index.html (服务器上某个资源名)
String url = "jdbc:mysql://127.0.0.1:3306/powernode";
协议:jdbc.mysql
IP:127.0.0.1
端口:3306
资源名:powernode(具体的数据库实列名)
说明: localhost 和 127.0.0.1都是本机的IP地址
3, 获取数据库操作对象 Connection class中的 createStatement()方法 Statement createStatement() 创建一个Statement用于将 SQL 语句发送到数据库的对象。 注意:以上三个方法都需要投掷SQL异常(查看JDK文档里面写的清清楚楚), so 都集中写在 try{} catch(SQLException e){}中 4, 执行SQL语句 怎么执行 : 又去找JDK文档,搜索 Statement class :去找方法 int executeUpdate(String sql) 执行给定的 SQL 语句,该语句可以是INSERT、 UPDATE、 orDELETE语句,也可以是不返回任何内容的 SQL 语句,例如 SQL DDL 语句。 int count = statement.executeUpdate(sql); //返回值是影响数据库的条数 5, 处理查询结果 没有查询步骤,这一步可以省略 6, 释放资源 :为了保证资源一定释放, 在finally语句快中关闭资源;并且要遵循从小到大依次关闭;关闭要分别对其 try catch。
import java.sql.Driver; // java.sql.Driver这是一个接口 , com.mysql.jdbc.Driver() 是一个实现类。 多看源码!!!
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
public class JDBCTest1 {
public static void main(String[] args){
Connection conn = null;
Statement statement = null;
try{
// 1,注册驱动
Driver driver = new com.mysql.jdbc.Driver(); // com.mysql.jdbc.Driver() 是一个实现类
DriverManager.registerDriver(driver);
// 2,获取连接
//String url = "jdbc:mysql://localhost/powernode";
String url = "jdbc:mysql://127.0.0.1/powernode";
String user = "root";
String password = "123456";
conn = DriverManager.getConnection(url,user,password); //获取连接对象
// 执行结果数据库连接对象 = com.mysql.cj.jdbc.ConnectionImpl@3d3fcdb0
System.out.println("数据库连接对象 = " + conn);
// 3, 获取数据库操作对象
// Statement statement = conn.createStatement(); // Stamement :数据库的对象
statement = conn.createStatement(); // Stamement :数据库的对象
// 4, 执行SQL语句
String sql = "insert into dept(deptno,dname,loc) values(50, '人事部' , '北京')";
//怎么执行 : 又去找JDK文档,搜索 Statement class :去找方法
// int executeUpdate(String sql) 执行给定的 SQL 语句,该语句可以是INSERT、 UPDATE、 orDELETE语句,也可以是不返回任何内容的 SQL 语句,例如 SQL DDL 语句。
int count = statement.executeUpdate(sql); //返回值是影响数据库的条数
System.out.println(count == 1 ? "保存成功" : "保存失败"); // 打开navicat 查看powernode数据库的dept表单 :发现确实如此
// 5, 处理查询结果
}catch(SQLException e){
e.printStackTrace();
}finally {
// 6, 释放资源
// 为了保证资源一定释放, 在finally语句快中关闭资源
// 并且要遵循从小到大依次关闭
// 关闭要分别对其 try catch
try {
if (statement != null){ // 所以 statement应该设置为全局变量
statement.close();
}
}catch (SQLException e){
e.printStackTrace();
}
try {
if (conn != null){ // 所以 statement应该设置为全局变量
conn.close();
}
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
运行结果:
点击navicat中的powernode数据库的dept表单:
点击刷新:
同理利用JDBC实现数据库的Update / delete操作与上面类似!!!
JDBC完成 delete 和 update 语句 int executeUpdate(String sql) 执行给定的 SQL 语句,该语句可以是INSERT、 UPDATE、 orDELETE语句,也可以是不返回任何内容的 SQL 语句,例如 SQL DDL 语句。 都是 statement 的 executeUpdate()函数
7,将连接数据库的所有信息配置到配置文件中
/*
实际开发中 不建议把连接数据库的信息写死到java程序中。
但是可以公司/银行自己在properties文件中,配置自己的数据库信息!!!
*/
代码小节6相同,仅需作如下两次修改:
1,添加配置文件:jdbc.properties, 将数据库相关信息填入配置文件中
2,在public static void main(){}中 使用资源绑定器 绑定配置文件。 配置文件读取数据
public class JDBCTest3 {
public static void main(String[] args){
// 使用资源绑定器 绑定配置文件。 配置文件读取数据
ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
String driver = bundle.getString("driver");
String url = bundle.getString("url");
String user = bundle.getString("user");
String password = bundle.getString("password");
Connection conn = null;
Statement stamement = null;
try{
// 1,注册驱动
// Driver driver = new com.mysql.jdbc.Driver(); // com.mysql.jdbc.Driver() 是一个实现类
// DriverManager.registerDriver(driver);
Class.forName(driver);
// 2,获取连接
// String url = "jdbc:mysql://127.0.0.1/powernode";
// String user = "root";
// String password = "123456";
conn = DriverManager.getConnection(url,user,password); //获取连接对象
8,实操 JDBC编程六步法 -- Select
/*
JDBC 完成 查询语句 和 查询结果集的处理(遍历结果集)
JDK文档 - ResultSet接口!
1,boolean next() 将光标从当前位置向前移动一行。
布尔值 next () 抛出SQL异常
将光标从当前位置向前移动一行。光标ResultSet最初位于第一行之前;第一次调用该方法 next使第一行成为当前行;第二次调用使第二行成为当前行,依此类推。
当对该next方法的调用返回时false,光标定位在最后一行之后。任何需要当前行的方法的调用ResultSet都会导致SQLException抛出异常。如果结果集类型是TYPE_FORWARD_ONLY,则由供应商指定其 JDBC 驱动程序实现在后续调用时是否返回false或抛出异常。 SQLExceptionnext
如果当前行打开输入流,则调用该方法next将隐式关闭它。ResultSet当读取新行时,对象的警告链将被清除。
返回:
true如果新的当前行有效; false如果没有更多行
投掷:
SQLException- 如果发生数据库访问错误或在关闭的结果集上调用此方法
*/
select语句 与 (insert update delete)语句不同之处在,第四步SQL语句的执行采用的函数不同;并且针对select查询的结果集还需要进行处理。 直接读代码,进行理解吧!
知识点:
1,采用配置文件读取数据库信息;
2,ResultSet executeQuery(String sql)函数
3,对ResultSet rs对象怎么处理 --》next()函数。and getString(),getInt(),getDouble()
4,释放资源的顺序:ResultSet, Statement,Connention.
import java.sql.*;
import java.util.*;
public class JDBCTest4 {
public static void main(String[] args){
// 0,只用配置文件读取数据库信息
ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
// 这里面的值 最好从properties里面复制
String driver = bundle.getString("driver");
String url = bundle.getString("url");
String user = bundle.getString("user");
String password = bundle.getString("password");
Connection conn = null;
Statement statement = null;
ResultSet rs = null; // 这是查询语句用 ,需要使用ResultSet对象进行接受查询结果集
try {
// 1,注册驱动 Class.forName的类加载动作
Class.forName(driver);
// 2, 获取连接
// static Connection getConnection(String url, String user, String password) 尝试建立与给定数据库 URL 的连接。
conn = DriverManager.getConnection(url, user, password);
//3,获取数据库操作对象
// Statement createStatement() 创建一个Statement用于将 SQL 语句发送到数据库的对象。
statement = conn.createStatement();
// 4, 执行SQL语句
/*
这里与增删改不一样啦!!!
Update/delete/insert:
int executeUpdate(String sql) 执行给定的 SQL 语句,该语句可以是INSERT、 UPDATE、 orDELETE语句,也可以是不返回任何内容的 SQL 语句,例如 SQL DDL 语句。
select:
ResultSet executeQuery(String sql) 执行给定的 SQL 语句,该语句返回单个 ResultSet对象。
返回一个ResultSet对象(相当于在数据库执行 select语句后得到的结果 存入 ResultSet rs对象中)
*/
String sql = "select empno,ename,sal from emp";
rs = statement.executeQuery(sql);
// 5,处理查询集
// 怎么处理ResultSet rs 查询结果集呢!!! 又去看JDK文档呗
boolean flag1 = rs.next(); // rs每调用一次next(),就会前进一行(“ = 二维表中 向下指一行”)
// if (flag1){
// // 光标指向的行有数据 ; 有数据就取数据
// // 怎么取,getString()方法的特点:不管数据库中的数据是什么类型,都以String的形成取出
// // JDBC中所有的下表都从1开始,而不是0开始 以下程序的1,2,3说的是第几列
// String empno = rs.getString(1);
// String ename = rs.getString(2);
// String sal = rs.getString(3);
//
// System.out.println(empno + "," + ename + "," + sal);
// }
while (rs.next()){
// 写1,2,3不健壮,应该直接写列名(查询结果集中的列名,不是数据库中的表列名)
// String empno = rs.getString(1);
// String ename = rs.getString(2);
// String sal = rs.getString(3);
//这里的列名 应该是查询结果的列名,即String sql = "select empno,ename as name,sal from emp";
String empno = rs.getString("empno");
String ename = rs.getString("ename"); //这里应该写 name
// 除了可以用getString()类型取出来以外,话可以用特定的类型取出:getDouble(), getInt()
double sal = rs.getDouble("sal"); // Double类型还可以参与运算
System.out.println(empno + "," + ename + "," + sal + 100);
}
}catch (Exception e){
e.printStackTrace();
}finally {
// 6,释放资源 : 从小到大!!
try{
if (rs != null) rs.close();
}catch (Exception e){
e.printStackTrace();
}
try{
if (statement != null) statement.close();
}catch (Exception e){
e.printStackTrace();
}
try{
if (conn != null) conn.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
运行结果:
D:\CScode\MySQL\JDBC>java JDBCTest4
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
7499,ALLEN,1600.0100
7521,WARD,1250.0100
7566,JONES,2975.0100
7654,MARTIN,1250.0100
7698,BLAKE,2850.0100
7782,CLARK,2450.0100
7788,SCOTT,3000.0100
7839,KING,5000.0100
7844,TURNER,1500.0100
7876,ADAMS,1100.0100
7900,JAMES,950.0100
7902,FORD,3000.0100
7934,MILLER,1300.0100
D:\CScode\MySQL\JDBC>