当前位置: 首页 > news >正文

JDBC从入门到精通-笔记(一):JDBC基本概念与开发基础

  视频资源:JDBC从入门到精通视频教程-JDBC实战精讲_哔哩哔哩_bilibili

JDBC定义与本质

概念

什么是JDBC:Java DataBase Connectivity

JDBC本质:SUN公司制定的一套接口(interface),java.sql.*。

                    面向接口调用,面向接口写实现类,都属于面向接口编程

                    接口相当于一种协议,调用者和使用者一般要遵守同一个接口的规则。

                    面向接口编程好处:解耦合-降低程序耦合度,提高程序扩展力。

                    多态机制是典型的面向抽象编程,使用时一般用父类引用对象,但调用子类方法。

                

JDBC接口的意义

为什么需要制定JDBC接口:因为每一个数据库的底层实现原理都不一样,如果没有接口,每连接一个新的数据库,都需要不同的代码实现。

数据库厂家编写JDBC接口的实现类,生成一组class文件,这组class文件称为驱动。所有的数据库驱动都是以jar包的形式存在,不是SUN公司提供,而是由各大数据库厂家提供,需要去各家官网下载。

数据库厂家编写JDBC接口的实现类,程序员调用这些类即可。

模拟JDBC本质

SUN公司 

/*SUN公司
*/
public interface JDBC {void getConnection(){}}

 数据库厂家

        MySQL 

/*MySQL数据库厂家负责实现JDBC实现类
*/public class MySQL implements JDBC {public void getConnection() {// 具体由MySQL实现System.out.println("连接MySQL数据库成功");}
}
// 实现类为MySQL驱动

        Oracle 

/*Oracle数据库厂家负责实现JDBC实现类
*/public class Oracle implements JDBC {public void getConnection() {// 具体由Oracle实现System.out.println("连接Oracle数据库成功");}
}
// 实现类为Oracle驱动

 Java程序员

/*Java程序员只需要面向JDBC写代码,不用在意数据库是哪个品牌
*/
public class JavaProgrammer {public void static main(String[] args) throws Exception{// JDBC jdbc = new MySQL();// JDBC jdbc = new Oracle();// 通过反射创建对象Class c = Class.forName("Oracle");JDBC jdbc = (JDBC) c.newInstance();// 以下代码都是面向接口调用,不用修改jdbc.getConnection();}
}

 用反射机制就可以把数据库信息放在配置文件中,分离数据。

jdbc.properties

className = Oracle

然后调用

/*Java程序员只需要面向JDBC写代码,不用在意数据库是哪个品牌
*/
import java.util.*;public class JavaProgrammer {public void static main(String[] args) throws Exception{// JDBC jdbc = new MySQL();// JDBC jdbc = new Oracle();// 通过反射创建对象// Class c = Class.forName("Oracle");ResourceBundle bundle = ResourceBundle.getBundle("jdbc");String className = bundle.getString("className");JDBC jdbc = (JDBC) c.newInstance();// 以下代码都是面向接口调用,不用修改jdbc.getConnection();}
}

这样,以后只要改配置文件就可以运行连接。

运行JavaProgrammer

java JavaProgrammer
> 连接Oracle数据库成功

 如果没有驱动的class文件直接运行,虽然编译能通过,但会报找不到类的错误,因为底层的实现类不存在。驱动非常重要。

使用JDBC进行开发

准备工作

从官网下载对应的驱动jar包,然后将其配置到环境变量中。

编程六步曲

  1. 注册驱动:告诉Java程序即将要连接的数据库是哪个
  2. 获取连接:表示JVM进程与数据库进程的通道打开,属于进程间通信,使用完后要关闭
  3. 获取数据库操作对象(执行sql语句的对象)
  4. 执行SQL语句:DQL DML
  5. 处理查询结果集:执行select语句后处理
  6. 释放资源:用完资源后一定要关闭资源

参考Java API 文档 - java.sql:Java Platform SE 8

注册驱动

        方法一:registerDriver(Driver driver) in class DriverManager

        注意点:

  • registerDriver是静态方法,可以直接用类名调用
  • 调用registerDriver时,其参数类型为Driver,但是在java.sql中,Driver只是一个接口,因此调用时必须使用对应驱动的实现类
  • 注意registerDriver可能存在异常,因此需要做异常处理。由于SqlException继承Exception,是受检异常,适合用try catch处理

public static void main(String[] args) {try {// 1、注册驱动Driver driver = new com.mysql.jdbc.Driver();// 多态,父类型引用指向子类型DriverManager.registerDriver(driver); // 不能直接new Driver,因为Driver是接口,需要new的Driver是实现类中的Driver// 2、获取数据库连接// 3、获取数据库操作对象// 4、执行sql// 5、处理查询结果集// 6、释放资源} catch (SQLException e) {e.printStackTrace();}}

        方法二:注意mysql的Driver实现类中,有静态代码块,会在类加载的时候执行一次。

 因此可以用反射机制调用该方法,方便将数据库驱动写到配置文件中去,此方法不需要接收返回值,更常用。

// 1、注册驱动// DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());Class.forName("com.mysql.jdbc.Driver"); 

获取数据库连接

         方法:getConnection(String url, String user, String password) in DriverManager

        注意点:

  • getConnection为静态方法,可以直接用类名调用
  • url是数据库地址,由 协议:// ip地址:端口号/数据库名称   组成
    • url拓展:url是统一资源定位符,其中通信协议表示规定好的数据传输格式,ip地址表示计算机地址,端口号表示app代号,资源名表示要访问的资源是什么。

  • 如果不是用mysql而是oracle数据库,其格式为jdbc:oracle:thin:@127.0.0.1:1521/数据库名称,相应的,调用时Driver也需要指向oracle的driver实现类。其余也是类似的,都有指定的协议,资源
  • 返回的数据库对象com.mysql.cj.jdbc.JDBC4Connection@xxxxx中,@之前的表示类名。实际使用发现com.mysql.jdbc.Driver已经过时,被com.mysql.cj.jdbc.Driver替代,所以得到的返回对象类名是com.mysql.jdbc.ConnectionImpl。
// 2、获取数据库连接String url = "jdbc:mysql://127.0.0.1:3306";String user = "root";String password = "333";Connection connection = DriverManager.getConnection(url, user, password);// 此时connection指向的是子类对象System.out.println("数据库连接对象:" + connection); // 返回数据库连接对象:com.mysql.cj.jdbc.ConnectionImpl@xxxxx

获取数据库操作对象

        方法:createStatement() in Connection

// 3、获取数据库操作对象Statement statement= connection.createStatement();

执行sql

        如果是增删改语句,使用Statement类中的executeUpdate(String sql)方法 

        JDBC中的sql语句不用写分号

// 4、执行sql// String sql = "select * from tableA";// 专门执行DML语句 - insert, update, delete// 返回值为影响数据库中的记录条数String sql = "insert into tableA ('USER_ACCOUNT', 'TEAM') VALUES ('abc@mail.com', 'IT')";int count = statement.executeUpdate(sql);

        如果是查询语句,使用Statement类中的executeQuery(String sql)方法,并把结果存储到ResultSet类中,保存结果集

//4、执行sqlString sql = "select * from tableA";// int executeUpdate(delete/insert/update)// ResultSet executeQuery(select)set = statement.executeQuery(sql); // executeQuery专门用于处理查询语句

处理结果集

         ResultSet中存在方法next(),是用于遍历结果集的迭代器,返回bool值。如果存在数据返回true,否则返回false。

 用rs.next()取出一行数据后,还需要通过rs中的get方法取出具体字段的value。

get方法有:getString(), getInt(),getDate()等。

getString()方法取出的数据无论在数据库是什么类型,返回的就是String类型。取数据时,可以通过列的下标(下标从1开始),也可以通过列名。推荐用列名,因为下标可能因为取顺序的数据发生改变。如果查询的时候对列名重命名了,必须用新的列名获取数据,否则会返回列不存在的错误。

getInt(),getDate()等方法不能随便使用,必须是数据库的底层数据类型与之相同的时候,才能正确执行,否则会返回数据类型无法转换的错误。

            //4、执行sqlString sql = "select id, name a, salary b from tableA";// int executeUpdate(delete/insert/update)// ResultSet executeQuery(select)rs = statement.executeQuery(sql); // executeQuery专门用于处理查询语句//5、处理结果集while (rs.next()) {// getString()方法:不管数据库数据类型是什么,都以String类型返回
//                String flow = rs.getString(2); // jdbc中所有下标从1开始, 2表示第二列
//                String scenario = rs.getString(3); // 第三列// 以查询结果的列名获取(因为查询结果可以给列名重命名)// 除了getString, 还可以用getInt, getDate等特定类型取出数据,但必须与数据库中的数据类型对应int id = rs.getInt("id");String name = rs.getString("a");String salary = rs.getDouble("b");System.out.println("id: " + (id+200) + " - name is '" + name + "' with salary '" + salry+ "'");// 返回 id: 1 - name is 'Jack' with salary '5000'

关闭资源

        写在finally中,需要释放的资源提前定义,否则finally中无法调用。 

        如果是查询语句,需要先关闭ResultSet。

public static void main(String[] args) {Connection connection = null;Statement statement = null;ResultSet rs = null;try {/*precondition*/connection = DriverManager.getConnection(url, user, password);// 此时connection指向的是子类对象System.out.println("数据库连接对象:" + connection);// 3、获取数据库操作对象statement= connection.createStatement();// 4、执行sql// do sth// 5、处理查询结果集// do sth} catch (SQLException e) {e.printStackTrace();} finally {// 6、释放资源// 在finally中释放资源,从小到大关闭,关闭时分别对其try catch// 为了能关闭资源,定义的时候就要把需要释放的资源放在try外面定义try {if (rs != null) {rs.close();}} catch (SQLException e) {e.printStackTrace();}try {if (statement != null) {statement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}

 将连接信息放入配置文件中

jdbc.properties

driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://127.0.0.1:3306/xxx
user = root
password = 333

用ResourceBundle调用数据 

package JDBCTest;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;// 将连接数据库的所有信息放到配置文件中
/*
实际开发不建议把连接数据库信息写死到程序中*/
public class JDBCTest04 {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 connection = null;Statement statement = null;try {// 1、注册驱动Class.forName(driver);// 2、获取数据库连接connection = DriverManager.getConnection(url, user, password);System.out.println("数据库连接对象:" + connection);// 3、获取数据库操作对象statement= connection.createStatement();// 4、执行sql// 专门执行DML语句 - insert, update, delete// 返回值为影响数据库中的记录条数String sql = "delete from users where id = '200'";// String sql = "update users set TEAM = 'a' where id = '200'";int count = statement.executeUpdate(sql);System.out.println(count == 1 ? "删除成功":"删除失败");// 5、处理查询结果集} catch (SQLException | ClassNotFoundException e) {e.printStackTrace();} finally {// 6、释放资源// 在finally中释放资源,从小到大关闭,关闭时分别对其try catch// 为了能关闭资源,定义的时候就要把需要释放的资源放在try外面定义try {if (statement != null) {statement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}
}

但实际开发不建议把连接数据库信息写死到程序中,用户体验很差。

注意:properties文件不能放错位置,否则会出现"Can't find bundle for base name jdbc, locale en_US" 的错误。要确保 jdbc.properties 文件位于类路径下。如果是标准的 Java 项目,将.properties 文件放在 src 目录下。对于 Maven 项目,应该放在 src/main/resources 目录下。

使用IDEA进行JDBC配置

新建Project后,File->Project Structure->Project Settings->Libraries

点击加号, 添加Java,选择数据库的jar包

 选择要导入的模块,如果有其他新模块新建的话,需要再导入一次。否则运行时会报类找不到错误。

然后就能在External libraries里看到了

相关文章:

  • 构建安全高效的前端权限控制系统
  • Flutter 实现软鼠标
  • 寻找重复数 - LeetCode 热题 100
  • QCombox绑定QMap
  • Map-JAVA面试常问
  • exzxml C语言XML解析库使用记录
  • selenium框架学习
  • Aigtek电压放大器的主要作用是什么
  • 华为手机数据恢复,2个技巧介绍,误删文件后的紧急处理
  • Python界面编辑器Tkinter布局助手 使用体验
  • 目标跟踪——KCF源码用python实现
  • 本地无法连接linux上的MariaDB数据库
  • 好用的便签是什么 电脑桌面上好用的便签
  • 【51单片机基础教程】点亮led
  • go编程中接口(interface)用法
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • 【Under-the-hood-ReactJS-Part0】React源码解读
  • Android单元测试 - 几个重要问题
  • Android框架之Volley
  • AWS实战 - 利用IAM对S3做访问控制
  • C++11: atomic 头文件
  • CSS实用技巧干货
  • ECMAScript入门(七)--Module语法
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • Java应用性能调优
  • linux学习笔记
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • Nacos系列:Nacos的Java SDK使用
  • nodejs调试方法
  • PHP的Ev教程三(Periodic watcher)
  • Selenium实战教程系列(二)---元素定位
  • spring + angular 实现导出excel
  • vue.js框架原理浅析
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 仿天猫超市收藏抛物线动画工具库
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 后端_ThinkPHP5
  • 面试遇到的一些题
  • 入手阿里云新服务器的部署NODE
  • 使用agvtool更改app version/build
  • 使用docker-compose进行多节点部署
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • ​必胜客礼品卡回收多少钱,回收平台哪家好
  • # Panda3d 碰撞检测系统介绍
  • #宝哥教你#查看jquery绑定的事件函数
  • #单片机(TB6600驱动42步进电机)
  • #进阶:轻量级ORM框架Dapper的使用教程与原理详解
  • (1)(1.13) SiK无线电高级配置(五)
  • (2024,RWKV-5/6,RNN,矩阵值注意力状态,数据依赖线性插值,LoRA,多语言分词器)Eagle 和 Finch
  • (7) cmake 编译C++程序(二)
  • (C语言)球球大作战
  • (Java入门)抽象类,接口,内部类