【MySQL】JDBC编程


前言

慢慢来吧 慢慢相遇吧!

主要是介绍 JDBC 的使用以及模板。


一、数据库编程必备条件

  1. 咱们的各种数据库都会提供API,以此来方便编程语言的控制
    (API:Application Programming Interface 应用程序编程接口:提供了一组类/方法供程序员使用)

  2. 不同种类的数据库提供的API不一样,这就会带来以下问题:
    ① 程序员需要掌握多种不同的数据库API,提高了学习成本;
    ② 如果一个项目要把数据库替换成另外一种,此时改动就很大

  3. java中为了解决上述问题,就提供了一组统一风格的数据库操作API,然后让这些数据库厂商来适配java的API;由此,掌握这一套java的API就能够操作各种数据库了。这一套java的API就叫做JDBC

  4. 在JDBC和各种数据库之间有一个驱动包(一组代码),该驱动包完成的是:数据库的原生API到JDBC API之间的转换。这个转换API的过程,在计算机属于中称为“适配(adapt)”

  5. 既然需要有驱动包进行接口之间的转换,那么就需要先把驱动包下载下来 并 导入到项目中

  6. 所以,数据库编程必备条件:编程语言、数据库、数据库驱动包。


二、下载导入驱动包jar包

  1. 如何下载驱动包jar包?
    ①Oracle官网;
    ②中央仓库:中央仓库
    (注意:安装时要和数据库服务器版本对得上——指的是大版本对应就行)
  2. .jar包本质上是一个压缩文件,类似于 .rar , .zip; 然后点进去jar包发现有很多.class文件,.jar包其实就是java程序发布的一种常见手段。
  3. 如何在项目中导入已经下载好的jar包?
    ① 先创建一个目录,与src同级(点的是directory);
    ② 把下载好的jar包拷贝到该目录下;
    ③ 右键新创建好的目录,然后选择 Add as Library… -->为了使IDEA能够识别目录中的jar包

三、JDBC编程(在IDEA中使用)

(通过java来操作数据库)

1. 创建数据源对象

数据源对象就描述了要访问的数据库是啥,在哪儿。

DataSource dataSource = new MysqlDataSource(); 

// 注意:DataSource 是接口,不能直接new
// DataSource来自于标准库JDBC中的一个接口
// MysqlDataSource 来自于mysql驱动包(是 DataSource 实现的一个类)

① 每种数据库都会提供对应的类来实现DataSource接口,也就是实现了向上转型(父类引用指向子类实例)
② 该代码其实就使用了“多态”。多态,可以认为就是“封装”的更进一步:封装是把实现细节隐藏起来让调用者不必考虑具体实现细节而可以直接使用,降低了调用者的使用成本和学习负担; 多态则是把实现类的类型也隐藏起来,调用者不仅不必考虑细节,连其具体类型也不用考虑,调用者考虑的信息就更少了。

((MysqlDataSource)dataSource).setURL("路径(自己写)"); 

// 向下转型(子类引用指向父类实例) // setURL
操作不是DataSource里面的,而是MysqlDataSource里面的,所以要把父类实例转为子类引用才能调用这个方法。

③ DataSource是服务于各种数据库的,而MysqlDataSource只服务于MySQL。
④ MySQL是一个客户端/服务器的程序,描述服务器的位置会使用URL这个概念来表示,而URL是获取网络上的资源; 但是有些数据库如SQLite就不是客户端/服务器结构,也就谈不上URL。所以,DataSource考虑到通用性就不能使用父类直接来进行调用,而是向下转型为子类各自调用。

dataSource.setURL(); // 这种写法也是完全ok的,这是没有使用多态的写法
//这种写法可能会让MysqlDataSource这个类型出现在很多地方,导致MySQL和项目耦合性就提高了;如果之后要换成其他数据库,就需要把所有出现MysqlDataSource这个类型的地方都进行修改。

⑤ 而使用多态,结合向上转型、向下转型的写法,则MysqlDataSource这个类型就只会出现一次,如果需要进行数据库的更换,改动就比较小;Mysql和项目的耦合性较低。

耦合性:一个大的程序里面包含很多个部分,这些部分之间关联性比较强则耦合性高;关联性比较低则耦合性较低
内聚:简单说就是把有关联的代码写到一起,不要到处乱写

⑥ URL:(Uniform Resource Location)唯一资源定位符,其实就是我们平时说的“网址”。(注意:需要使用 引号 来指明地址)
其实就是:jdbc:mysql://服务器地址:端口/数据库名?参数名=参数值

如:" jdbc:mysql://127.0.0.1:3306/testbit?character=utf8&useSSL=false"

① jdbc:mysql: 协议名称
② 127.0.0.1:IP地址:描述了网络上的一个主机位置,和日常所说的“地址”差不多;而127.0.0.1又是一个特殊的IP地址,表示本机IP! (即:无论本机IP是啥,都可以使用127.0.0.1表示自己的IP地址,类似于this——这叫环回IP
(注: 当前数据库(外面自己写的代码,不是那个黑色框)和服务器(安装好的 “服务” 里的 mysql 就是))都是在自己的电脑上,所以直接使用本机IP就行)
③ 3306:端口号:用来区分主机上的不同应用程序的(安装数据库的时候有个环节是配置端口号的,默认就是3306 )
④ testbit:就是要访问的数据库
⑤ character=utf8:客户端使用的字符集,要和服务器这边一致
⑥ &useSSL=false:是否加密:true是加密,false是不加密

⑦ DataSource就描述了能够找到数据库的数据;URL里面体现的是数据库服务器的位置以及数据库的名字

⑧ 在已知别人的IP地址时也不一定能够访问其数据库:

要保证其他电脑的IP可达;
即使IP可达,也要保证端口可访问;
数据库要配置成允许其他客户端访问

((MysqlDataSource)dataSource).setUser(“root”);
((MysqlDataSource)dataSource).setPassword(“密码”);
// 即使mysql没有设置密码也要写,但是写成空字符串就行

-----以上描述的是数据在哪
下面要开始访问:访问的时候要先和数据库服务器建立连接,然后再进行后续操作。

2. 让代码和数据库服务器建立连接

Connection connection = dataSource.getConnection(); 
// 此时可能会抛出异常,进行throws 或 try...catch

① 注:受查异常(出现异常则必须显式处理 throws try…catch…) 、 非受查异常

② 使用Connection来表示连接;Connection应该使用JDBC里的Connection(也就是标准库java.sql里的Connection),而不是MYSQL驱动包里的Connection

③(抛出异常中显示 Access denied 表示用户名或密码错误)

④ 那我的电脑没有插网线也没连WiFi,为啥还是能够连接成功?
——因为mysql的客户端和服务器是在同一个主机上的,是通过127.0.0.1 环回IP来连接的,与外面连不连接网络没关系。

3. 构造要执行的SQL语句+ 预处理【构造请求】

String sql = “insert into 表名 values(....); 
  // 注意双引号中使用单引号
PreparedStatement statement = connection.preparedStatement(sql);
// 注:有时自己输入时可能需要占位符? 以及setXXX

① sql语句发给数据库,数据库就得对这个SQL语句进行解析(可以理解为编译);这个解析过程其实是比较消耗时间、消耗资源的;数据库服务器日理万机,要处理很多客户端的请求,如果把所有的工作都让服务器来完成就会让系统资源更加紧张。
② 所以就使用 PreparedStatement 进行预处理。
③ 注:utf8mb4是mysql独有的操作,抛开mysql配置文件其他地方见不到;所以 统一写做 utf8

4. 执行sql:执行sql【发送请求,读取响应】

① 执行方法有两个:executeUpdate对应插入、删除、修改语句 ——返回一个int,也就是受影响的行数。
② executeQuery对应查询——返回值则是临时表数据,类型是ResultSet结果集。

5. 遍历结果集(只针对executeQuery)

6. 完成之后,关闭释放相关资源

statement.close();
connection.close();  // 释放的是内存资源和一些软件资源

① 之前的statement语句对象和connection连接对象,都是需要消耗资源的; 我们常说的资源,主要是一些硬件资源(有时候也指软件资源)
② 很多操作都是要消耗资源的,比如new一个对象就要消耗一定的资源(这里是内存资源)。
③ 那么为什么之前的对象没有手动释放呢?
——Java内置了 垃圾回收GC机制 帮我们自动释放
④【释放资源的顺序要和申请资源的顺序正好相反!
先创建的后释放,后创建的先释放】

如果希望用户在程序运行的时候可以自己输入数据进行插入,怎么办呢?
—— 字符串拼接方式:如 ’ " + name+ " ’ (外面的单引号如果是字符串形式就需要加) 这样的形式。

但是该方式存在一些弊端:①代码非常乱,不直观;
②不安全,容意引发SQL诸如漏洞(由于自己输入,那就可能会存在输入了一些操作SQL的语句来破坏数据库。

——因此:不应该手动拼接SQL,而是应该借助PreparedStatement内部提供的SQL拼装机制,这样会对拼接的内容进行更严格的校验检查,避免SQL注入(注:下标从1开始! n代表第n个占位符?))】

【相关补充】

  1. JDBC优势:

① Java语言访问数据库操作完全面向抽象接口编程
② 开发数据库应用不用限定在特定数据库厂商的API
③ 程序的可移植性大大增强

  1. 数据库连接Connection
    1) Connection接口实现类由数据库提供,获取Connection对象通常有两种方式:
    ① 一种是通过DriverManager(驱动管理类)的静态方法获取:
// 加载JDBC驱动程序
Class.forName("com.mysql.jdbc.Driver");
// 创建数据库连接
Connection connection = DriverManager.getConnection(url);

② 一种是通过DataSource(数据源)对象获取。实际应用中会使用DataSource对象。

DataSource ds = new MysqlDataSource();
((MysqlDataSource)ds).setUrl("jdbc:mysql://localhost:3306/test");
((MysqlDataSource) ds).setUser("root");
((MysqlDataSource) ds).setPassword("root");
Connection connection = ds.getConnection();

2)这两种方式的区别是:

① DriverManager类来获取的Connection连接,是无法重复利用的,每次使用完以后释放资源时,通过connection.close()都是关闭物理连接
② DataSource提供连接池的支持。连接池在初始化时将创建一定数量的数据库连接,这些连接是可以复用的,每次使用完数据库连接,释放资源调用connection.close()都是将Conncetion连接对象回收

3)和DriveManager相比,还是更推荐使用dataSource:因为

① DriveManager使用了反射。(不到万不得已不要使用反射,代价有点大; 像一些库和框架为了做到更好的通用性/兼容性,会考虑使用反射)
② DriveManager每次getConnection都会重新建立连接,但是dataSource则是可以内置连接池,可以达到连接复用,提高效率。
(注:池存在的目的就是为了 重复利用资源,达到提高效率的目的。简单说就是:资源准备好,随时用随时拿)

4)实际开发中其实很少使用jdbc,一般会使用一些 库/框架来简化数据库的操作(如MyBatis)

  1. 在查询时:resultSet.getXXX的参数可以是列名,但是同样是从1开始;建议按照列名来取(加引号)。
    (考虑:可读性 + 列名多情况)
  • 不只是条件查询,各种查询如insert + select 、 聚合查询、联合查询、子查询、合并查询都是同理
  1. Statement对象
    Statement对象主要是将SQL语句发送到数据库中。JDBC API中主要提供了三种Statemen对象:

① Statement:用于执行不带参数的简单SQL语句。
② PreparedStatement:用于执行带或不带参数的SQL语句; SQL语句会预编译在数据库系统; 执行速度快于Statement对象。
③ CallableStatement:用于执行数据库存储过程的调用。

  1. ResultSet对象:
    1)ResultSet对象它被称为结果集,它代表符合SQL语句条件的所有,并且它通过一套getXXX方法提供了对这些行中数据的访问。
    2)ResultSet里的数据一行一行排列,每行有多个字段,并且有一个记录指针,指针所指的数据行叫做当前数据行,我们只能来操作当前的数据行。
    3)我们如果想要取得某一条记录,就要使用ResultSet的next()方法 ,如果我们想要得到ResultSet里的所有记录,就应该使用while循环。

四、面试问题

  1. 数据库连接有哪些方式?分别有什么区别?
    答:① 两种连接方式:DriverManager(驱动管理类)的静态方法获取 + DataSource(数据源)对象获取。
    ② 区别:连接的重复利用(池) + 释放资源

  2. 数据库Statement和PreparedStatement有什么区别?
    答:①SQL语句带参数
    ②预编译
    ③执行速度


五、参考代码

主要模仿模板。

  1. 增删改查:
    增删改查

  2. 实例:

图书管理系统
①新增貂蝉同学的借阅记录:诗经,从2019年9月25日17:50到2019年10月25日17:50
②查询计算机分类下的图书借阅信息
③修改图书《深入理解Java虚拟机》的价格为61.20
④删除id最大的一条借阅记录

图书管理

六、另

  1. 数据库特点:高共享、低冗余、独立性高、具有完整性。
  2. 范式:范式是符合某一种级别的关系模式的集合。关系数据库中的关系必须满足一定的要求,满足不同程度要求的为不同范式。目前关系数据库有六种范式:第一范式( 1NF )、第二范式( 2NF )、第三范式( 3NF )、 Boyce-Codd 范式( BCNF )、第四范式( 4NF )和第五范式( 5NF )。

1)满足最低要求的范式是第一范式( 1NF )。
2)在第一范式的基础上进一步满足更多要求的称为第二范式( 2NF ),其余范式以次类推
3)一般说来,数据库只需满足**第三范式( 3NF )**就行了。

① 第一范式:主属性(主键)不为空且不重复,字段不可再分(存在非主属性对主属性的部分依赖)。
② 第二范式:如果关系模式是第一范式,每个非主属性都没有对主键的部分依赖
③ 第三范式:如果关系模式是第二范式,没有非主属性对主键的传递依赖和部分依赖
④ BCNF范式:所有属性都不传递依赖于关系的任何候选键。

  1. if(条件,表达式1,表达式2);
    这里,如果条件为真(非0),则返回表达式1;条件为假(0)返回表达式2

  2. 在select部分,既有单值列,又有分组函数时,所有出现的单值列必须作为分组列处理;且 分组函数(如:sum/max/min/avg) 只返回一个值。

  3. 记住一句话,当要删除的记录在数据库中不存在的时候,是不会报错的。所以,两个delete是ok的。

  4. MySQL实现了四种通信协议:TCP/IP协议、Unix Socket协议、Share Memory协议、Named Pipes协议。

  5. 排它锁()X)又称为写锁。共享锁(S)称为读锁。


THINK

  1. JDBC使用步骤总结

① 创建数据源对象 DataSource
② 建立连接 Connection
③ 构造sql + 预处理PreparedStatement
④ 执行sql (两种不同的execute)
⑤ ( 如果是select,则需要对结果集进行遍历)
⑥ 释放资源(逆序释放!)

  1. 面试题
  2. 注意另外所补充的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 21
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

'Dream是普通小孩耶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值