0
点赞
收藏
分享

微信扫一扫

MySQL入门与实践

黎轩的闲暇时光 2022-02-09 阅读 37

1. 简介

MySQL是关系型数据库

2. MySQL安装

  1. 官网下载MySQL的zip压缩包
    下载地址: https://dev.mysql.com/downloads/mysql/
  1. D:\program\MySQL\mysql-8.0.28-winx64\bin 添加环境变量
  2. D:\program\MySQL\mysql-8.0.28-winx64\ 目录下创建 my.ini配置文件,内容如下
[mysqld]
basedir=D:\program\MySQL\mysql-8.0.28-winx64\
datadir=D:\program\MySQL\mysql-8.0.28-winx64\data\
port=3306
skip-grant-tables
  1. 管理员模式启动CMD, 执行如下命令

    1. mysqld -install // 执行安装操作
    2. mysqld --initialize-insecure --user=mysql //执行初始化操作,此时会出现dataidr指向的data目录
    3. net start mysql // 启动mysql服务 (可在任务管理器的服务进程中查看mysql状态)
    4. mysql -u root -p12345678a : 进入mysql管理界面(如果没有密码可以不设置,直接mysql -u root -p键入)
    5. use mysql : 进入mysql仓库 (进入mysql后,切记语句加分号)
    6. alter user 'root'@'localhost' identified by '123456';: 修改mysql的user表中的密码为123456(即登录mysql的密码)
    1. 修改my.ini文件,删除最后一句 skip-grant-tables (# 可注释)
    2. 如果修改了密码,建议重启mysql服务并重新登录(重启命令行窗口)
      net stop mysql : 停止mysql服务
      net start mysql : 启动mysql服务
      mysql -u root -p123456 : 密码登录mysql管理器
  2. 安装配置完成

3. 安装SQLyog

下载地址: https://www.onlinedown.net/soft/24926.htm?src=360

  1. 安装
  2. 初始化配置, 填写mysql时的配置信息,直接点击连接即可连接到mysql
    在这里插入图片描述
  3. 新建一个school数据库
    在这里插入图片描述
  1. 新建student表
    在这里插入图片描述
  2. 查看并操作student表中的数据(增删查改)
    在这里插入图片描述
    在这里插入图片描述

4. 数据库释义

4.1 数据库的列类型

加粗为常用,其他仅了解

数值

tinyint1字节
smallint2字节
mediumint3字节
int4字节
bigint8字节
float4字节
double8字节
decimal金融行业解决失精问题

字符串

char字符串固定大小0~255
varchar可变字符串0~65535
tinytext微型文本2^8-1
text文本串2^16-1

日期类型

dateYYYY-MM-DD
timeHH:mm:ss
datetimeYYYY-MM-DD HH:mm:ss
timestamp时间戳
year年份表示

4.2 数据库的字段属性

Unsigned无符号整数,不可为负数
zerofill位数不足,使用0填充
自增设计主键, 整数类型,可设计起始值和步幅
非空必须赋值,否则报错
默认如果不赋值,则使用默认

4.3 数据表引擎(数据表类型)

MYISAMINNODB
事务支持不支持(一旦某条sql存在报错,则全部提交失败)支持
数据行锁定不支持(例如执行查询时,锁定整张表)支持
外键约束不支持支持
全文索引支持(可在文本内容中查询)不支持
大小较小较大,为前者的两倍
安全性一般高(流行的主要原因)

创建的数据库文件的物理存在位置 : mysql根目录下的data目录中

5. 数据库相关操作命令

sql命令必须以分号结尾
不区分大小写
特殊字符使用飘包裹

– 单行注释

show databases; 查看所有的数据库

use school; 进入school数据库

show tables; 查看当前库中的所有表

describe student; 显示student表中的所有信息

create database yang; 创建名称为yang的数据库

exit; 退出mysql

5.1 操作数据库

  1. 创建数据库
create database [if not exists] yang character set utf8 collate utf8_general_ci;  -- 创建yang数据库 并设置特性 和校正字符集 ,如果它不存在
  1. 删除数据库
    drop databse [if exists] yang; 删除数据库yang,如果它存在
  2. 使用数据库
    use yang; 使用名称为yang的数据库
  3. 查看数据库
    show databases; 查看所有的数据库

5.2 创建表

  • 设置 字段名 类型 [非空] [默认] [注释]
  • 设置 主键
  • 设置 表类型(引擎) 字符集
  • 字段名建议用``包裹
create table if not exists `student`(
	`id` int(4) not null AUTO_INCREMENT COMMENT '学号',
	`name` varchar(30) not null default '匿名' comment '姓名',
	`pwd` varchar(16) not null default '123456' comment '密码',
	`sex` varchar(2) not null default '男' comment '性别',
	`birthday` datetime default null comment '出生日期',
	`address` varchar(100) default null comment '地址',
	`email` varchar(50) default null comment '邮箱',
	primary key(`id`)
) engine=innodb default charset=utf8

5.3 逆向查看sql语句

show create database school -- 查看创建school数据库的sql语句
show create table student --查看创建student表的sql语句
desc student --查看student表

5.4 修改 删除 表

修改表名
alter table 旧表名 rename as 新表名
alter table teacher rename as teacher1

增加表字段
alter 数据库名 表名 add 字段名 属性
alter table teacher add age int(3)

修改字段属性
alter 数据库名 表名 modify 字段名 新属性
alter table teacher modify age varchar(3)

修改字段名称
alter 数据库名 表名 change 旧字段名 新字段名
alter table teacher change age age1

删除表字段
alter 数据库名 表名 drop 字段名
alter table teacher drop age

删除表
drop 数据库名 [if exists] 表名
drop table teacher

6. MySQL数据管理

6.1 外键(不建议使用)

为一个表添加物理外键,不建议使用,当存在多个表时,因为外键的约束关系,导致部分表无法删除

为数据表中的某个id字段添加外键约束
alter table 表名 add constraint 约束名 foreign key(表中作为外键的字段) references 关联表('关联表的字段')
例子 alter table student add constraintKF_gradeidforeign key(gradeid) references grade('id')

外键的最佳实践: 用程序去实现

6.2 DML (数据操作语言)

6.2.1 增

insert into 表名([字段名1,字段名2,字段名3,...]) values('值1','值2','值3',...)
insert intograde(gradename) values('大二')

同时插入多条数据
例: insert into student(name,pwd) values (‘张三’,‘123’),(‘李四’,‘456’)

6.2.2 改

修改单个属性, 带条件

update `grade` set `gradename`='大学一年级' where `gradeid`=1

修改多个属性

update `student` set `name`='小明',`email='123@qq.com'` where id=1

修改id区间内的属性

int类型可使用基本的 >   <   =   != 等基本运算符号

//使用between
update `grade` set `gradename`='大学' where `gradeid` between 2 and 4

修改多个条件下的属性

update `student` set `name`='小明' where `name`='李华' and `sex`='女'
update `student` set `name`='小明' where `name`='李华' or `sex`='女'

6.2.3 删

删除student表下的id=1的数据

delete form `student` where `id`=1;

清空student表中的所有数据

truncate `student`

delete 和 truncate的区别:

  • truncate 会将自增属性归零
  • truncate 不会影响事务

6.3 DQL查询数据 *

概述

在这里插入图片描述
语法中的顺序不可颠倒

示例表

student表

studentNostudentName
1小明
2小红
3小华

result表

studentNosubjectNostudentResult
1180
2170
3190
1297
2289
3268

subject表

subjectNosubjectName
1语文
2数学

6.3.1 简单查询

查询student表中的全部数据

select * from student

查询student表中的 studentNo 和 studentName 属性

select `studentNo`,`studentName` from student

//为studentNo 和 studentName 属性分别起别名为 学号 和 学生姓名,注意这里的别名不需要引号包裹
select `studentNo` as 学号,`studentName` as 学生姓名 from student

//使用函数为查询的studentName属性拼接字符串并输出
select concat('姓名:',studentName) from student

6.3.2 去重

select distinct 属性名 from 表名

//在result表中查询 studentNo字段,并将查询出来的数据进行去重操作
select distinct `studentNo` from result;

6.3.3 数据库中表达式

select 表达式 from 表名

select version()   --查看系统版本
select 100*3-1 as 计算结果   -- 用来计算
select @@auto_increment_increment  -- 查询自增步长

-- 从result表中查询出 studentNo和studentResult字段,并将所有的 studentResult字段值+1
select `studentNo`,`studentResult`+1 as '加分后成绩' from result

6.3.3 查询中的where条件子句

//查询考试成绩在 95~100之间的学生
select `studentNo`,`studentResult` from student where studentResult>=95 and studentResult<=100;

//查询学号等于1000的学生
select `studentNo`,`studentResult` from student where studentNo=1000;

//查询学号不等于1000的所有学生
select `studentNo`,`studentResult` from student where not studentNo=1000;

//在student表中查询地址为null的学生的学号和名称
select `studentNo`,`studentName` from `student` where `address` is null;

//在student表中查询地址为不为null的学生的学号和名称
select `studentNo`,`studentName` from `student` where `address` is not null;

//在student表中查询 学号属于 (1000,1001,1002) 集合 的学生的姓名
select `studentName` from `student` where `studentNo` in (1000,1001,1002);

6.3.4 模糊查询

like语句中,%匹配任意个字符, _匹配一个字符

--  查询student表中姓刘的同学
select `studentNo`,`studengName` from `student` where `studentName` like '刘%'

-- 查询student表中姓刘且名称为两个字的同学
select `studentNo`,`studengName` from `student` where `studentName` like '刘_';

-- 查询student表中名称中包含刘字的同学
select `studentNo`,`studengName` from `student` where `studentName` like '%刘%';

6.3.5 联表查询 join on

几种情况:
在这里插入图片描述
1.select * from A表 left join B表 on A表.字段= B表.字段

  • 以A表的数据(包含联表条件字段的)为基准,用B表的数据作为辅助填充

2.select * from A表 right join B表 on A表.字段= B表.字段

  • 以B表的数据(包含联表条件字段的)为基准,用A表的数据作为辅助填充

3.select * from A表 inner join B表 on A表.字段= B表.字段

  • 以A表和B表中的交叉数据(联表条件字段存在于两个表中)为基准,用两张表的数据为辅助填充

思路:

  1. 确定要查哪些字段
  2. 查看这些字段需要用到哪些表
  3. 从两张表开始,逐步进行多表的查看

示例:

// student学生表(包含学号,和学生信息), result成绩表(包含学号,科目编号,成绩), subject科目表(包含科目编号,科目名称)
// 从上述三个表中 通过联表查询 ,查出 学号 学生姓名 考试科目名称 考试成绩 

select `s.studentNo`,`studentName`,`subjectName`,`studentResult`
from student as s   -- 基础 从student表中查询
right join result as r  -- 右加入联查(此时决定以成绩表信息为基准,因为有成绩的同学才参加了考试)
on s.studentNo = r.studentNo -- 确定联表条件( 学号相同)
inner join subject as sub -- 在上述sql语句结果的基础上, 交叉加入科目表
on r.subjectNo=sub.subjectNo -- 确定联表条件(科目编号形同)

6.3.6 自联表查询

核心: 一张表拆为两张一样的表

存在这样一张表

  • 表关系: 数据库的pid = 软件开发的categoryId

在这里插入图片描述
即可拆分为下面两张表
在这里插入图片描述
查询示例:

select a.`categoryName` as '父栏目',b.'categoryName' as '子栏目'
from `category` as a,`category` as b   -- 同一张表,当作两张表来使用
where a.`categoryid` = b.`pid`

6.3.7 分页和排序

order bylimit

示例

select `studentNo`,`studentName`,`studentResult` from `student` -- 从student表中查询 学号 姓名 成绩
order by `studentResult` ASC  --  按照studentResult字段升序排列   ; ASC 升序  DESC 降序
limit 0,5   -- 从索引0开始,取5个数据

6.3.8 子查询和嵌套查询

示例

//查询考试科目为 高等数学 切分数不少于80分的同学的学号和姓名

//使用联表查询的方式
select s.`studentNo`,s.`studentName` 
from student as s
inner join result as r
on s.studentNo = r.studentNo
inner join subject as sub
on r.subjectNo = sub.subjectNo
where subjectName='高等数学' and studentResult>=80;

//使用嵌套查询的方式 (现有表中不存在的字段条件,通过子查询语句,获取到符合条件的该字段的值)
select studentNo,studentName from student
where studentNo in (
	select studentNo from result where studentResult>=80 and subjectNo= (
		select subjectNo from subject where subjectName='高等数学'
	)
)

6.3.9 MySQL常见函数

//md5加密
MD5('字符串')

数字运算

select abs(-8)  -- 绝对值
select ceiling(9.4) -- 向上取整
select floor(8.5) -- 向下取整
select rand() -- 获取0~1之间的一个随机数
select sign(10) -- 判断一个数的符号    0->0   负数-> -1   整数->1

字符串运算

select char_length('一个字符串'); -- 获取字符串长度
select concat('姓名',`studentName`) from student -- 拼接字符串, 在查询出的studentname字段前添加 "姓名"字符串
select insert('一段要被局部替换的字符串',2,3,'要替换的文字'); -- 从索引2开始,三个长度的字符串替换
select lower('ABC'); -- 转换为小写
select upper('abc'); -- 转换为大写
select instr('abcdefg','d'); -- 返回在字符串中第一次出现'd'的脚标
select replace('abcdefg','abc','xyz'); -- 将字符串中的adb替换为xyz
select substr('abcdefg',4,2); -- 从脚标4开始,截取长度为2的字符串
select reverse('12345'); -- 反转字符串

-- 示例
-- 在student表中,查询出刘姓的同学,并将其改为周姓后输出
select replace(`studentName`,'刘','周') from student where studentName like '刘%'; 

时间和日期函数

select current_date(); -- 当前日期
select curdate(); -- 获取当前日期
select now() -- 获取本地时间
select localtime() -- 本地时间
select sysdate() -- 系统时间

6.3.10 聚合函数(常用) 及 分组过滤查询

count()计数
sum()求和
avg()平均值
max()最大值
min()最小值

示例

select count(`studentName`) from student;  -- 从student表中查询studentName获取的行数,为null的不计入
select count(*) from student;   -- 获取数据行数,计入null
select count(1) from student;

分组过滤查询

-- 查询不同课程的平均分 最高分 最低分
select subjectName,avg(studentResult) as 平均分,max(studentResult),min(studentResult)
from result as r  -- 从成绩表中查找
inner join subject as sub  -- 联查科目表
on r.subjectNo = sub.subjectNo --联查条件
group by r.subjectNo  -- 通过subjectNo字段进行分组(subjectNo相同的数据为一组),此时聚合函数以组为单位进行计算
having 平均分>80; -- 在分组查询时,where条件语句报错,如果需要添加过滤条件,则使用 having

7. 事务

7.1事务原则(ACID)

示例: A有1000元 B有200元 C有500元 , 现在A向B转账100元

原子性 A:1000-100 ; B: 200+100 ; 这两条语句为一个整体,同时执行或者同时失败

一致性:A向B转账后, 两人的金钱总和前后一致, 都为1200元

持久性: 事务一旦提交便不可逆, 将被持久到数据库中

隔离性: A向B转账的同时, C也向B转账, 此时他们互相隔离互不影响

7.2 事务相关语句

set autocommit = 0; – 关闭自动提交 (MySQL默认开启了事务的自动提交)
start transaction; – 开启事务
commit; – 提交事务
rollback; – 回滚事务
set autocommit = 1; – 重新开启自动提交

savepoint 保存点名称; 标记保存点
rollback to savepoint 保存点名称; 回滚到标记的保存点
release savepoint 保存点名称; 撤销保存点

7.2 事务实现转账

示例:

  • 了解事务的开启 , 提交, 回滚操作
create database shop character set utf8 collate utf8_general_ci;  -- 创建shop数据库
 
use shop;  -- 使用shop数据库

-- 创建account表 , 模拟小明借给小花500的操作
create table `account`(
	`id` int(3) not null auto_increment,
	`name` varchar(20) not null,
	`money` decimal(9,2),
	primary key(`id`)`shop`
)engine=innodb default charset=utf8;   

insert into `account`(`name`,`money`) values('小明',3000),('小花',1000); -- 增加小明和小花的原始数据

set autocommit = 0; -- 关闭自动提交

start transaction;  -- 开启一个事务,后续的sql语句则被事务归并为一个操作,即原子性

-- 小明借钱给小花  则小明账户-500 与 小花账户+500 应该同时发生,隶属于同一组事务,所以应该开启事务绑定
update `account` set `money`=money-500 where `name` = '小明';
update `account` set `money`=money+500 where `name` = '小花';

commit; -- 提交事务, 提交后数据将被持久化

rollback; -- 回滚, 数据会被回滚到刚开始事务时的状态(前提是没有commit事务)

set autocommit = 1; -- 开启自动提交

7.3 事务在java层面的使用

try{
	sql相关语句...
	commit();
}catch(Exception e){
	rollback();
}

8. 索引

8.1 索引分类

1. 主键索引 (primary key)
唯一标识, 只能存在一个主键索引

2. 唯一索引 ( unique key)
列唯一,避免重复列的出现, 可为多个列设置唯一索引

3. 常规索引 (key / index)
默认的, 也可以通过 key/ index来设置

4. 全文索引 (fulltext)
在特定的数据库引擎下才有,用于快速定位数据

设置索引示例

-- 创建表时添加索引
CREATE TABLE IF NOT EXISTS `student`(
	`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '学号',
	`identityCard` INT(18) NOT NULL COMMENT '身份证号',
	`name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
	`pwd` VARCHAR(16) NOT NULL DEFAULT '123456' COMMENT '密码',
	`sex` VARCHAR(2) NOT NULL DEFAULT '男' COMMENT '性别',
	`birthday` DATETIME DEFAULT NULL COMMENT '出生日期',
	`address` VARCHAR(100) DEFAULT NULL COMMENT '地址',
	`email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
	PRIMARY KEY(`id`),   -- 设置id为主键 
	UNIQUE KEY `identitycard` (`identitycard`),   -- 设置 identitycard 为唯一索引(其他列不可同名)
	KEY `email` (`email`)   -- 设置email为常规索引
) ENGINE=INNODB DEFAULT CHARSET=utf8

-- 查看student表中的索引信息
show index from student;

-- 在已经创建的表中添加全文索引
alter 数据库名 表名 add 索引类型 索引名(表中字段名)
alter table student add fulltext index `studentname`(`studentname`);
或者
create 索引类型 索引名 on 表名(字段名)
例:create index id_app_user on app_user(`name`);

使用索引示例

-- 使用 全文索引查询 student表中  studentname中包含'刘' 的信息
select * from student where match(studentname) against('刘');

使用 explain 分析sql执行的状况

explain select * from student;      -- 可以从查询结果中的rows列中得知查询的次数

8.2 索引原则

  • 索引不是越多越好
  • 不要对经常变动的数据加索引
  • 小数据量的表不需要加索引
  • 索引一般加在常用来查询的字段上

索引的数据类型

  • Hash数据结构
  • 默认为Btree

9. 数据库用户管理

9.1 使用sqlyog创建新用户

  1. 创建新的用户
    在这里插入图片描述
  2. 给创建用户设置权限
    在这里插入图片描述
  3. 为用户创建新的链接
    在这里插入图片描述

9.2 使用sql语句操作用户

用户表: mysql.user

-- 创建用户并设置初始密码
CREATE USER yang IDENTIFIED BY '123456';

-- 修改指定用户的密码( 遵循最新版本语法 可能已不适用)
SET PASSWORD FOR yang = PASSWORD('11111');

-- 重命名
RENAME USER yang TO yangf

-- 给指定用户授权 (ALL PRIVILEGES 代表除了'给别人授权'的全部权限)   *.* 表示 库.表
GRANT ALL PRIVILEGES ON *.* TO yangf

-- 查询某个用户的权限
SHOW GRANTS FOR yangf 
SHOW GRANTS FOR root@localhost  -- 查看管理员权限

-- 撤销权限  (撤销yangf 库.表 下的全部权限)
REVOKE ALL PRIVILEGES ON *.* FROM yangf 

-- 删除用户
DROP USER yangf

10. 数据库备份

MySQL数据库备份的方式:

10.1. 直接拷贝物理文件

物理文件位置: mysql根目录下的data目录

10.2. 使用sqlyog可视化工具

在这里插入图片描述

10.3. 使用mysqldump 命令行导出

使用 win + R 打开命令行窗口

导出

```
# 导出单个表
# mysqldump -h主机名 -u用户名 -p密码 数据库 表名 >物理磁盘位置/文件名
mysqldump -hlocalhost -uroot -p123456 school student >D:/a.sql

# 导出多个表
# mysqldump -h主机名 -u用户名 -p密码 数据库 表1名 表2名 >物理磁盘位置/文件名
mysqldump -hlocalhost -uroot -p123456 school student result >D:/b.sql

# 导出数据库
# mysqldump -h主机名 -u用户名 -p密码 数据库 >物理磁盘位置/文件名
mysqldump -hlocalhost -uroot -p123456 school >D:/b.sql

```

导入

```
# 1. 登录mysql
mysql -uroot -p123456
# 2. 切换到指定的数据库 ( 如果导入的是数据库 则无需此操作)
use school
# 3. source 备份文件 (将a.sql中的表数据导入到school数据库中)
source D:/a.sql

# 或者 (推荐上面的方式)
mysql -u用户名 -p密码 库名< 备份文件
```

11. 数据库设计规范

11.1 三大范式

第一范式
原子性: 保证每一列不可再分

第二范式
保证第一范式的前提下
每张表只描述一件事情

第三范式
前提: 满足第一范式和第二范式
确保数据表中的每一列数据都和主键直接相关,而不能间接相关

12. JDBC(重点)

12.1 JDBC的意义

在这里插入图片描述

12.2 第一个JDBC程序

  1. 模拟数据库数据

    CREATE DATABASE shop CHARACTER SET utf8 COLLATE utf8_general_ci;  -- 创建shop数据库
     
    USE shop;  -- 使用shop数据库
    
    -- 创建account表 , 模拟小明借给小花500的操作
    CREATE TABLE `account`(
    	`id` INT(3) NOT NULL AUTO_INCREMENT,
    	`name` VARCHAR(20) NOT NULL,
    	`money` DECIMAL(9,2),
    	PRIMARY KEY(`id`)`shop`
    )ENGINE=INNODB DEFAULT CHARSET=utf8;   
    
    INSERT INTO `account`(`name`,`money`) VALUES('小明',3000),('小花',1000);
    
  2. IDEA创建一个基础的java程序

  3. 在程序的根目录下添加 lib目录 ,并添加mysql-connector-java.jar
    jar包的下载地址: https://mvnrepository.com/artifact/mysql/mysql-connector-java/8.0.28

  4. 创建java类,并编写jdbc连接程序

    public class JdbcDemo {
    
        public static void main(String[] args) throws Exception {
            //1. 加载驱动 ( 将该类放入到类加载器中   , Driver中存在的静态方法会执行)
            Class.forName("com.mysql.jdbc.Driver");
    
            //2. 编写链接的  url和用户信息
            //jdbc:mysql://主机地址:端口号/数据库名称?使用Unicode编码&字符集为utf-8&使用安全协议
            String url = "jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&useSSL=true";
            String userName= "root";
            String pwd = "123456";
    
            //3. 建立连接,获取数据库对象 Connection
            Connection connection = DriverManager.getConnection(url, userName, pwd);
            //可进行事务的回滚和提交
            //connection.setAutoCommit(true);
            //connection.rollback();
            //connection.commit();
    
    
            //4. 获取操作Sql语句的对象 Statement
            Statement statement = connection.createStatement();
            //statement.executeQuery(""); //执行sql的查询语句,返回查询结果,并存放在结果集中
            //statement.execute(""); //可执行全部的sql语句
            //statement.executeUpdate("");  //可执行插入 更新 删除命令 , 返回受影响的行数
    
            //5. 执行sql语句, 并返回执行结果ResultSet   获取数据类似与jsonObject, 遍历方式等同于迭代器
            String sql = "select * from account";
            ResultSet resultSet = statement.executeQuery(sql);
    
            //resultSet.beforeFirst(); //移动到第一行
            //resultSet.afterLast(); //移动到最后一行
            //resultSet.absolute(2); //移动到第二行
            //resultSet.next(); //获取到下一个数据
            
            //6. 迭代器处理返回结果
            while (resultSet.next()){
                Object name = resultSet.getObject("name");
                Object money = resultSet.getObject("money");
                System.out.println("查询到的信息   name:" + name + "  money: " + money );
            }
    
            //7. 释放资源
            resultSet.close();
            statement.close();
            connection.close();
        }
    }
    

12.3 封装工具类实现JDBC

  1. 在工程的src目录下创建 db.properties 配置文件,内容如下

    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&useSSL=true
    username=root
    password=123456
    
  2. 创建JDBCUtils类

    
    public class JDBCUtils {
    
        private static String driver = "";
        private static String url = "";
        private static String userName = "";
        private static String password = "";
    
        static {
            try {
                //加载db配置文件
                InputStream inputStream = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
                Properties properties = new Properties();
                properties.load(inputStream);
    
                //读取配置文件信息
                driver = properties.getProperty("driver");
                url = properties.getProperty("url");  //url决定了连接哪一个数据库
                userName = properties.getProperty("username");
                password = properties.getProperty("password");
    
                //驱动只需要加载一次
                Class.forName(driver);
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        //获取连接
        public static Connection getConnection() throws SQLException {
            return DriverManager.getConnection(url, userName, password);
        }
    
        //释放资源
        public static void release(Connection connection, Statement statement, ResultSet resultSet) {
            try {
                if (connection != null) connection.close();
                if (statement != null) statement.close();
                if (resultSet != null) resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    
  3. 工具类执行查询语句

    
    public class TestQuery {
    
        public static void main(String[] args) {
    
            Connection connection = null;
            Statement statement = null;
            ResultSet resultSet = null;
    
            try {
                connection = JDBCUtils.getConnection();
                statement = connection.createStatement();
    
                String sql = "select * from account";
    
                resultSet = statement.executeQuery(sql);
    
                while (resultSet.next()) {
                    String name = resultSet.getString("name");
                    System.out.println("查询到的name: " + name);
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                JDBCUtils.release(connection,statement,resultSet);
            }
        }
    }
    

12.4 SQL注入的安全问题

当需要执行的sql语句 是由外部传递的参数拼接 而成时,外部传入的参数可以通过 传入 ' or '1=1'等类似参数,破坏sql原意,从而导致数据泄露问题

12.5 PrepareStatement对象

结合上述创建的JDBCUtils工具类,示例:


public class PrepareStatementTest {

    public static void main(String[] args) {

        Connection connection = null;
        
        //PreparedStatement 防止sql注入问题的本质是 将传入的value值 重新转换成了字符串 ,并忽略的转义符号
        PreparedStatement statement = null;
        ResultSet resultSet = null;

        try {
            connection = JDBCUtils.getConnection();

            //通过 ?充当占位符, 组成预设的sql语句
            String sql = "select * from account where id = ?";

            //通过预设的sql语句获取到 PreparedStatement对象
            statement = connection.prepareStatement(sql);

            //为占位符设置value  statement.setInt(占位符角标从1开始,对应的值);
            // 不同类型的参数都可以找到对应的函数进行设置
            statement.setInt(1,1);

            //执行sql语句
            resultSet = statement.executeQuery();

            while (resultSet.next()) {
                String name = resultSet.getString("name");
                System.out.println("查询到的name: " + name);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.release(connection,statement,resultSet);
        }
    }
}

12.6 JDBC操作MySQL事务

示例 (操作的为7.2中的数据库数据)


public class TestTransaction {
    public static void main(String[] args) {

        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;

        try {
            connection = JDBCUtils.getConnection();

            //关闭自动提交, 即开启事务
            connection.setAutoCommit(false);

            /*************** 事务 start **********************/
            String sql = "UPDATE `account` SET `money`=money-500 WHERE `name` = '小明'";
            statement = connection.prepareStatement(sql);
            statement.executeUpdate();

            String sql2 = "UPDATE `account` SET `money`=money+500 WHERE `name` = '小花'";
            statement = connection.prepareStatement(sql2);
            statement.executeUpdate();
            /*************** 事务 end **********************/

            connection.commit();

            connection.setAutoCommit(true);
            System.out.println("事务执行完成");


        } catch (SQLException e) {
            
            System.out.println("事务执行异常");
            try {
                connection.rollback(); //事务执行异常,执行回滚操作, 不添加此句子,也会自动回滚
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            JDBCUtils.release(connection,statement,resultSet);
        }
    }
}

13. 使用IDEA连接MySQL

  1. 连接数据库
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  2. 操作数据库表数据
    在这里插入图片描述
  3. 执行sql语句
    在这里插入图片描述

14. 数据库连接池

为了解决 数据库频繁的连接,释放造成的系统资源浪费问题

可使用的第三方库(可自行百度实现方式):

  1. DBCP
  2. C3P0
举报

相关推荐

0 条评论