1. 简介
MySQL是关系型数据库
2. MySQL安装
- 官网下载MySQL的zip压缩包
下载地址: https://dev.mysql.com/downloads/mysql/
- 将
D:\program\MySQL\mysql-8.0.28-winx64\bin
添加环境变量 - 在
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
-
管理员模式启动CMD, 执行如下命令
mysqld -install
// 执行安装操作mysqld --initialize-insecure --user=mysql
//执行初始化操作,此时会出现dataidr指向的data目录net start mysql
// 启动mysql服务 (可在任务管理器的服务进程中查看mysql状态)mysql -u root -p12345678a
: 进入mysql管理界面(如果没有密码可以不设置,直接mysql -u root -p
键入)use mysql
: 进入mysql仓库 (进入mysql后,切记语句加分号)alter user 'root'@'localhost' identified by '123456';
: 修改mysql的user表中的密码为123456(即登录mysql的密码)
- 修改my.ini文件,删除最后一句
skip-grant-tables
(# 可注释) - 如果修改了密码,建议重启mysql服务并重新登录(重启命令行窗口)
net stop mysql
: 停止mysql服务
net start mysql
: 启动mysql服务
mysql -u root -p123456
: 密码登录mysql管理器
-
安装配置完成
3. 安装SQLyog
下载地址: https://www.onlinedown.net/soft/24926.htm?src=360
- 安装
- 初始化配置, 填写mysql时的配置信息,直接点击连接即可连接到mysql
- 新建一个school数据库
- 新建student表
- 查看并操作student表中的数据(增删查改)
4. 数据库释义
4.1 数据库的列类型
加粗为常用,其他仅了解
数值
tinyint | 1字节 |
smallint | 2字节 |
mediumint | 3字节 |
int | 4字节 |
bigint | 8字节 |
float | 4字节 |
double | 8字节 |
decimal | 金融行业解决失精问题 |
字符串
char | 字符串固定大小 | 0~255 |
varchar | 可变字符串 | 0~65535 |
tinytext | 微型文本 | 2^8-1 |
text | 文本串 | 2^16-1 |
日期类型
date | YYYY-MM-DD |
time | HH:mm:ss |
datetime | YYYY-MM-DD HH:mm:ss |
timestamp | 时间戳 |
year | 年份表示 |
4.2 数据库的字段属性
Unsigned | 无符号整数,不可为负数 |
zerofill | 位数不足,使用0填充 |
自增 | 设计主键, 整数类型,可设计起始值和步幅 |
非空 | 必须赋值,否则报错 |
默认 | 如果不赋值,则使用默认 |
4.3 数据表引擎(数据表类型)
MYISAM | INNODB | |
事务支持 | 不支持(一旦某条sql存在报错,则全部提交失败) | 支持 |
数据行锁定 | 不支持(例如执行查询时,锁定整张表) | 支持 |
外键约束 | 不支持 | 支持 |
全文索引 | 支持(可在文本内容中查询) | 不支持 |
大小 | 较小 | 较大,为前者的两倍 |
安全性 | 一般 | 高(流行的主要原因) |
创建的数据库文件的物理存在位置 : mysql根目录下的data目录中
5. 数据库相关操作命令
sql命令必须以分号结尾
不区分大小写
特殊字符使用飘包裹
– 单行注释
show databases;
查看所有的数据库
use school;
进入school数据库
show tables;
查看当前库中的所有表
describe student;
显示student表中的所有信息
create database yang;
创建名称为yang的数据库
exit;
退出mysql
5.1 操作数据库
- 创建数据库
create database [if not exists] yang character set utf8 collate utf8_general_ci; -- 创建yang数据库 并设置特性 和校正字符集 ,如果它不存在
- 删除数据库
drop databse [if exists] yang;
删除数据库yang,如果它存在 - 使用数据库
use yang;
使用名称为yang的数据库 - 查看数据库
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 constraint
KF_gradeidforeign key(
gradeid) references grade('id')
外键的最佳实践: 用程序去实现
6.2 DML (数据操作语言)
6.2.1 增
insert into 表名([字段名1,字段名2,字段名3,...]) values('值1','值2','值3',...)
例 insert into
grade(
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表
studentNo | studentName |
---|---|
1 | 小明 |
2 | 小红 |
3 | 小华 |
result表
studentNo | subjectNo | studentResult |
---|---|---|
1 | 1 | 80 |
2 | 1 | 70 |
3 | 1 | 90 |
1 | 2 | 97 |
2 | 2 | 89 |
3 | 2 | 68 |
subject表
subjectNo | subjectName |
---|---|
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表中的交叉数据(联表条件字段存在于两个表中)为基准,用两张表的数据为辅助填充
思路:
- 确定要查哪些字段
- 查看这些字段需要用到哪些表
- 从两张表开始,逐步进行多表的查看
示例:
// 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 by 和 limit
示例
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创建新用户
- 创建新的用户
- 给创建用户设置权限
- 为用户创建新的链接
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程序
-
模拟数据库数据
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);
-
IDEA创建一个基础的java程序
-
在程序的根目录下添加 lib目录 ,并添加
mysql-connector-java.jar
jar包的下载地址:https://mvnrepository.com/artifact/mysql/mysql-connector-java/8.0.28
-
创建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
-
在工程的
src目录
下创建db.properties
配置文件,内容如下driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&useSSL=true username=root password=123456
-
创建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(); } } }
-
工具类执行查询语句
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
- 连接数据库
- 操作数据库表数据
- 执行sql语句
14. 数据库连接池
为了解决 数据库频繁的连接,释放造成的系统资源浪费问题
可使用的第三方库(可自行百度实现方式):
- DBCP
- C3P0