前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL与JDBC精简笔记

MySQL与JDBC精简笔记

作者头像
Rochester
发布2020-09-01 10:30:12
3.9K0
发布2020-09-01 10:30:12
举报
文章被收录于专栏:牛人NR牛人NR

一、数据库

1.数据库的基本概念

1.数据库的英文单词:

DataBase 简称:DB

2. 什么是数据库?

用于存储和管理数据的仓库。

3 .数据库的特点:

1.持久化存储数据的。其实数据库就是一个文件系统; 2.方便存储和管理数据; 3.使用了统一的方式操作数据库 — SQL

4. MySQL的安装和卸载

具体自己百度查询

5. MySQL的登录和退出

1. MySQL的登录
  1. ​ 方式1:mysql -uroot -p密码
  2. ​ 方式2:mysql -h连接目标的IP地址 -uroot -p连接目标的密码
  3. ​ 方式3:mysql –host=ip –user=root –password=连接目标的密码
2. MySQL的退出
  1. 方式1:exit
  2. 方式2:quit

2. SQL

1.什么是SQL?

Structured Query Language:结构化查询语言

其实就是定义了操作所有关系数据库的规则。每一种数据库操作的方式存在不一样的地方,称为“方言”。

2. SQL通用语法

  1. SQL语句可以单行或多行书写,以分号结尾;
  2. 可使用空格和缩进来增强语句的可读性;
  3. MySQL数据库的SQL语句不区分大小写,关键字建议用大写书写;
  4. 有3种注释方式:
    1. 单行注释:– 注释内容;(注意–后必须有空格)
    2. 单行注释:# 注释内容;(MySQL特有方法)
    3. 多行注释:/* 注释 */

3. SQL分类

  1. DDL(Data Definition Language)数据定义语言 用来定义数据库对象:数据库,表,列等。 关键字:create,drop,alter等。
  2. DML(Data Manipulation Language)数据操作语言: 用来对数据库中表的数据进行增删改。 关键字:insert,delete,update等。
  3. DQL:(Data Query Language)数据查询语言: 用来查询数据库中表的记录(数据)。 关键字:select,where等。
  4. DCL:(Data Control Language)数据控制语言(了解) 用来定义数据库的访问权限和安全级别,及创建用户。 关键字:GRANT,REVOKE等。

3. DDL:操作数据库、表

1. 操作数据库:CRUD

1. C(Create):创建
  • 创建数据库:
    • create database 数据库名称;
代码语言:javascript
复制
mysql> create database db1;
Query OK, 1 row affected (0.15 sec)
  • 创建数据库,判断不存在,再创建:
    • create database if not exists 数据库名称;
代码语言:javascript
复制
mysql> create database if not exists db2;
Query OK, 1 row affected (0.18 sec)
  • 创建数据库,并制定字符集:
    • create database 数据库名称 character set 字符集名;
代码语言:javascript
复制
mysql> create database db3 character set gbk;
Query OK, 1 row affected (0.16 sec)
2. R(Retrieve):查询
  • 查询所有数据库的名称:
    • show databases;
代码语言:javascript
复制
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| db1                |
| db2                |
| db3                |
| db4                |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
8 rows in set (0.37 sec)
  • 查询某个数据库的字符集:查询某个数据库的创建语句
    • show create database 数据库名称;
代码语言:javascript
复制
mysql> show create database db3;
+----------+------------------------------------------------------------------------------------------------+
| Database | Create Database                                                                                |
+----------+------------------------------------------------------------------------------------------------+
| db3      | CREATE DATABASE `db3` /*!40100 DEFAULT CHARACTER SET gbk */ /*!80016 DEFAULT ENCRYPTION='N' */ |
+----------+------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
3. U(Update):修改
  • 修改数据库的字符集
    • alter database 数据库名称 character set 字符集名称;
代码语言:javascript
复制
mysql> alter database db4 character set utf8;
Query OK, 1 row affected, 1 warning (0.49 sec)
4. D(Delete):删除
  • 删除数据库
    • drop database 数据库名称;
代码语言:javascript
复制
mysql> drop database db4;
Query OK, 0 rows affected (0.21 sec)
  • 判断数据库存在,存在再删除
    • drop database if exists 数据库名称;
代码语言:javascript
复制
mysql> drop database if exists db3;
Query OK, 0 rows affected (0.17 sec)
5. 使用数据库
  • 查询当前正在使用的数据库名称
    • select database();
代码语言:javascript
复制
mysql> select database();
+------------+
| database() |
+------------+
| NULL       |
+------------+
1 row in set (0.00 sec)
  • 使用数据库:
    • use 数据库名称;
代码语言:javascript
复制
mysql> use db2;
Database changed
mysql> select database();
+------------+
| database() |
+------------+
| db2        |
+------------+
1 row in set (0.00 sec)

2.操作表:

1. C(Create):创建
1. 语法
代码语言:javascript
复制
create table 表名(
    列名1 数据类型1,
    列名2 数据类型2,
    ...
    列名n 数据类型n
);
* 注意:最后一列,不需要加逗号(,)
2. 数据库类型
  1. int:整数类型
    • age int,
  2. double : 小数类型
    • score double(5,2)

    *注意 :5表示总共取5位,2表示小数点后2位

  3. date:日期,只包含年月日,yyyy-MM-dd
  4. datetime:日期,包含年月日时分秒 yyyy-MM-dd HH:mm:ss
  5. timestamp:时间错类型(自动赋值使用当前系统时间):包含年月日时分秒:yyyy-MM-dd HH:mm:ss
    • 如果将来不给这个字段赋值,或赋值为null,则默认使用当前的系统时间,来自动赋值
  6. varchar:字符串
    • name varchar(20):表示姓名最大占用20个字符
      • zhangsan 8个字符 张三 2个字符
  • 练习:
    • 在db1数据库中创建一个名为student数据表,
    • 里面包含的列有id,name,age,score,birthday,创建日期(默认) 展示表结构:
    代码语言:javascript
    复制
    mysql> desc student;
    +-------------+-------------+------+-----+---------+-------+
    | Field       | Type        | Null | Key | Default | Extra |
    +-------------+-------------+------+-----+---------+-------+
    | id          | int         | YES  |     | NULL    |       |
    | name        | varchar(20) | YES  |     | NULL    |       |
    | age         | int         | YES  |     | NULL    |       |
    | score       | double(3,1) | YES  |     | NULL    |       |
    | birthday    | date        | YES  |     | NULL    |       |
    | insert_time | timestamp   | YES  |     | NULL    |       |
    +-------------+-------------+------+-----+---------+-------+
    6 rows in set (0.00 sec)
代码语言:javascript
复制
mysql> use db1;
Database changed
mysql> create table student(
    ->          id int,
    ->          name varchar(20),
    ->          age int,
    ->          score double(3,1),
    ->          birthday date,
    ->          insert_time timestamp
    -> );
Query OK, 0 rows affected, 1 warning (0.28 sec)
3.复制表
代码语言:javascript
复制
create table 表名 like 被复制的表名;
2. R(Retrieve):查询
  • 查询某个数据库中所有的表名称
    • show tables;
代码语言:javascript
复制
mysql> use mysql;
Database changed
mysql> show tables;
+---------------------------+
| Tables_in_mysql           |
+---------------------------+
| columns_priv              |
| component                 |
| db                        |
| user                      |
+---------------------------+
4 rows in set (0.10 sec)
  • 查询表结构
    • desc 表明;
代码语言:javascript
复制
mysql> desc db;
+-----------------------+---------------+------+-----+---------+-------+
| Field                 | Type          | Null | Key | Default | Extra |
+-----------------------+---------------+------+-----+---------+-------+
| Host                  | char(255)     | NO   | PRI |         |       |
| Db                    | char(64)      | NO   | PRI |         |       |
| User                  | char(32)      | NO   | PRI |         |       |
+-----------------------+---------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
3. U(Update):修改
1. 修改表名
代码语言:javascript
复制
alter table 表名 rename to 新的表名;
2. 修改表的字符集
代码语言:javascript
复制
alter table 表名 character set 新字符集名称;
3. 添加一列
代码语言:javascript
复制
alter table 表名 add 列名 数据类型;
4.修改列名称、类型
代码语言:javascript
复制
1.alter table 表名 change 列名 新列名 新数据类型;
2.alter table 表名 modify 列名 新数据类型;    -- 只修改列的数据类型
5. 删除列
代码语言:javascript
复制
alter table 表名 drop 列名;
4. D(Delete):删除
  1. drop table 表名;
  2. drop table if exists 表名;
代码语言:javascript
复制
mysql> drop table if exists stu;
Query OK, 0 rows affected (0.68 sec)

4. DML: 增删改表中数据

1. 添加数据:

代码语言:javascript
复制
* 语法:
insert into 表名(列名1,列名2,...列名n) values(值1,值2,...值n);
  • 注意:
    1. 列名和值要一一对应;
    2. 如果表名后,不定义列名,则默认给所有列添加值;
    3. 除了数字类型,其它类型需要使用引号(单双都可以)引起来。
代码语言:javascript
复制
insert into 表名 values(值1,值2,...值n);
  • 示例: 输出结果:
image-20200405094412034
image-20200405094412034
代码语言:javascript
复制
INSERT INTO stu(id,NAME,age) VALUES(1001,'露娜',18); -- 给指定列添加数据

INSERT INTO stu VALUES(1002,'貂蝉',19,99.9,'2000-01-01',NULL); -- 默认全部添加数据

SELECT * FROM stu; -- 查询表中的数据

2. 删除数据:

代码语言:javascript
复制
* 语法:
delete from 表名 where 条件; -- 删除具体某一行数据
  • 注意:
    1. 如果不加条件,则删除表中所有记录;
    2. 如果要删除所有记录:
代码语言:javascript
复制
1.delete from 表名; --不推荐使用。有多少条记录就会执行多少次删除操作,效率低;
2.truncate table 表名; --推荐使用,效率更高;先删除表,然后再创建一张一模一样的表。
  • 示例:
代码语言:javascript
复制
DELETE FROM stu WHERE id=1001;

DELETE FROM stu;

TRUNCATE TABLE stu;

3. 修改数据:

代码语言:javascript
复制
* 语法:
update 表名 set 列名 = 值1,列名2 = 值2,... [where 条件];
  • 注意: 如果不加任何条件则会将表中所有记录全部修改。
  • 示例:
代码语言:javascript
复制
UPDATE stu SET age = 20 WHERE id = 1002; -- 修改某一列某一数据

UPDATE stu SET age = 21; -- 修改表中全部某一数据的值为统一的值

5. DQL: 查询表中的记录

1. 语法:

代码语言:javascript
复制
select
    字段列表
from
    表名列表
where
    条件列表
group by
    分组字段
having
    分组之后的条件
order by
    排序
limit
    分页限定

2. 基础查询:

1.多个字段的 查询
代码语言:javascript
复制
select 字段名1,字段名2,... from 表名;
2. 去重重复:
代码语言:javascript
复制
distinct
3. 计算列:
  • 一般可以使用四则运算计算一些列的值。(一般只会进行数值型的计算);
  • ifnull(表达式1,表达式2)
    1. null参加的运算,计算结果都为null;
    2. 表达式1:代表哪个字段需要判断是否为null;
    3. 表达式2:如果该字段为null后的替换纸。
4. 起别名:
代码语言:javascript
复制
as : as也可以省略
  • 示例:
代码语言:javascript
复制
-- 创建表
CREATE TABLE student (
    id INT, -- 编号
    NAME VARCHAR(20), -- 姓名
    age INT, -- 年龄
    sex VARCHAR(5), -- 性别
    address VARCHAR(100), -- 地址
    math INT, -- 数学
    english INT -- 英语
);

-- 添加数据
INSERT INTO student(id,NAME,age,sex,address,math,english) VALUES(1,'马云',55,'男','杭州',66,78),
(2,'马化腾',45,'女','深圳',98,87),(3,'马克涛',55,'男','香港',56,77),(4,'柳岩',20,'女','湖南',76,65),
(5,'柳青',20,'男','湖南',86,NULL),(6,'刘德华',57,'男','香港',99,99),
(7,'马德',22,'女','香港',99,99),(8,'德玛西亚',18,'男','南京',56,65);

-- 查询编号和姓名
SELECT id,NAME FROM student;

-- 查询地址
SELECT address FROM student;

-- 去重,地址里面有重复的
SELECT DISTINCT address FROM student;

-- 计算每个人成绩总分
SELECT NAME,math,english,math + english FROM student;

-- 因为null参加的运算,结果都为null
-- 所以利用ifnull计算
SELECT DISTINCT NAME,math,english,math + IFNULL(english,0) FROM student;

-- 起别名
SELECT DISTINCT NAME AS 姓名,math AS 数学,english AS 英语,math + IFNULL(english,0) AS 总分 FROM student;

-- 起别名 中 AS 也可以省略
SELECT DISTINCT NAME 姓名,math 数学,english 英语,math + IFNULL(english,0) 总分 FROM student;

3. 条件查询

  1. where子句后跟条件;
  2. 运算符
    • <, >, <=, >=, =, <>
    • between…and
    • in(集合)
    • like
    • is null
    • and 或 &&
    • or 或 ||
    • not 或 !
  • 示例:
代码语言:javascript
复制
-- 查询年龄大于20的人
SELECT * FROM student WHERE age > 20;

-- 查询年龄等于20的人
SELECT * FROM student WHERE age = 20;

-- 查询年龄大于等于20的人
SELECT * FROM student WHERE age >= 20;

-- 查询年龄不等于20的人
SELECT * FROM student WHERE age != 20;    -- 方式1
SELECT * FROM student WHERE age <> 20;    -- 方式2

-- 查询年龄大于等于20,小于等于30的人
SELECT * FROM student WHERE age >= 20 AND age <= 30;  -- 方式1
SELECT * FROM student WHERE age >= 20 && age <= 30;  -- 方式2
SELECT * FROM student WHERE age BETWEEN 20 AND 30;  -- 方式3

-- 查询年龄为22岁,18岁,25岁的人的信息
SELECT * FROM student WHERE age = 22 OR age = 18 OR age = 25;  -- 方式1
SELECT * FROM student WHERE age IN (22,18,25);

-- 查询英语成绩为null的人
-- select * from student where english = null;    -- 错误写法,NULL值不能使用 = 或者 != 进行判断
SELECT * FROM student WHERE english IS NULL;

-- 查询英语 成绩不为NULL的人
SELECT * FROM student WHERE english IS NOT NULL;
  1. 模糊查询( like ):
    • 占位符:
      • _ :单个任意字符;
      • % :多个任意字符
  • 示例:
代码语言:javascript
复制
-- 查询姓马的人
SELECT * FROM student WHERE NAME LIKE '马%';

-- 查询名字第二个字为化的人
SELECT * FROM student WHERE NAME LIKE '_化%';

-- 查询名字是3个 字的人
SELECT * FROM student WHERE NAME LIKE '___';  -- "三个_"

-- 查询名字中包含德的人
SELECT * FROM student WHERE NAME LIKE '%德%';

4. 排序查询

  • 语法:
    • order by 子句
    • order by 排序字段1 排序方式1,排序字段2 排序方式2…
  • 排序方式:
    • ASC :升序,默认的;
    • DESC : 降序。
  • 注意:
    • 如果有多个排序条件,则当前边的条件值一样时,才会判断第二条件。
  • 示例:
代码语言:javascript
复制
-- 查询数学成绩,按升序排序
SELECT * FROM student ORDER BY math ASC;

-- 查询数学成绩,按降序排序
SELECT * FROM student ORDER BY math DESC;

-- 查询数学成绩,按照降序排序,如果数学成绩一样,按照英语成绩降序排序
SELECT * FROM student ORDER BY math DESC,english DESC;

5. 聚合函数

  1. count : 计算个数
    • 一般选择非空的列:主键;
    • count( * )
  2. max :计算最大值
  3. min :计算最小值
  4. sum :计算和
  5. avg :计算平均值

注意

  • 聚合函数的计算,排除null值;
    • 解决方案:
      1. 选择不包含非空的列进行计算;
      2. ifnull函数。

  • 示例:
代码语言:javascript
复制
-- 计算数学个数
SELECT COUNT(math) FROM student;

-- 计算英语个数
SELECT COUNT(IFNULL(english,0)) FROM student; -- 如果为null,可使用ifnull函数

-- 计算个数
SELECT COUNT(*) FROM student; -- 哪列没有NULL,就自动选取哪列计算个数

-- 计算数学最高分
SELECT MAX(math) FROM student;

-- 计算数学最小分
SELECT MIN(math) FROM student;

-- 计算数学总和
SELECT SUM(math) FROM student;

-- 计算数学平均分
SELECT AVG(math) FROM student;

6. 分组查询

  1. 语法:group by 分组字段;
  2. 注意:
    • 分组之后查询的字段:分组字段、聚合函数
    • where 和 having 的区别?
      1. where 在分组之前进行限定,如果不满足条件。则不参与分组;having在分组之后限定,如果不满足结果,则不会被查询出来。
      2. where 后 不可以 跟聚合函数,having 可以进行聚合函数的判断。
  • 示例:
代码语言:javascript
复制

-- 按照性别分组,分别查询男、女同学的数学平均分
SELECT sex,AVG(math) GROUP BY sex;

-- 按照性别分组,分别查询男、女同学的数学平均分、人数
SELECT sex,AVG(math),COUNT(id) FROM student GROUP BY sex ;

-- 按照性别分组,分别查询男、女同学的数学平均分、人数,要求:分数低于70分的,不参与分组
SELECT sex,AVG(math),COUNT(id) FROM student WHERE math > 70 GROUP BY sex;

-- 按照性别分组,分别查询男、女同学的数学平均分、人数,要求:分数低于70分的,不参与分组,
-- 分组之后,人数要大于2个人
SELECT sex,AVG(math),COUNT(id) FROM student WHERE math > 70 GROUP BY sex HAVING COUNT(id) > 2; -- 方式1
SELECT sex,AVG(math),COUNT(id) 人数 FROM student WHERE math > 70 GROUP BY sex HAVING 人数 > 2; -- 方式2

7. 分页查询

  1. 语法:
    • limit 开始的索引,每页查询的条数;
  2. 公式:
    • $$ 开始的索引 = (当前的页码 - 1) * 每页显示的条数 $$
  3. 注意: limit 是一个MySQL“方言”。

示例:

代码语言:javascript
复制
-- 每页显示3条记录
SELECT * FROM student LIMIT 0,3; -- 第1页
SELECT * FROM student LIMIT 3,3; -- 第2页
SELECT * FROM student LIMIT 6,3; -- 第3页

8. 约束

1. 概念和分类

  • 概念:对表中的数据进行限定,保证数据的正确性、有效性和完整性。
  • 分类:
    1. 主键约束:primary key
    2. 非空约束:not null
    3. 唯一约束:unique
    4. 外键约束:foreign key

2. 非空约束:not null

代码语言:javascript
复制
-- 创建表时添加非空约束
CREATE TABLE stu (
    id INT,
    NAME VARCHAR(20) NOT NULL  -- name为非空
);

-- 创建完表后,再添加非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;

-- 删除约束
ALTER TABLE stu MODIFY NAME VARCHAR(20);  -- 相当于修改

3. 唯一约束:UNIQUE

代码语言:javascript
复制
-- 创建表时,添加唯一约束
CREATE TABLE stu (
    id INT,
    phone_num VARCHAR(20) UNIQUE
);
* 注意:在mySQL中,唯一约束限定的列的值可以有多个NULL

-- 删除唯一约束
ALTER TABLE stu DROP INDEX phone_num;

-- 在创建表后,添加唯一约束
ALTER TABLE stu MODIFY phone_num VARCHAR(20) UNIQUE;

4. 主键约束:primary key

  1. 注意:
    1. 含义:非空且唯一
    2. 一张表只能有一个字段为主键;
    3. 主键就是表中记录的唯一标识。
  2. 在创建表时,添加主键约束;
代码语言:javascript
复制
CREATE TABLE stu(
    id INT PRIMARY KEY,
    NAME VARCHAR(20)
);
  1. 删除主键;
代码语言:javascript
复制
ALTER TABLE stu DROP PRIMARY KEY;
  1. 创建完表后,添加主键。
代码语言:javascript
复制
ALTER TABLE stu MODIFY id INT PRIMARY KEY;
  • 自动增长
    1. 概念: 如果某一列是数值类型的,使用 auto_increment 可以来完成自动增长;
    2. 在创建表时,添加主键约束,并且完成主键自动增长;
    3. 删除自动增长;
    代码语言:javascript
    复制
    ALTER TABLE stu MODIFY id INT ;
    1. 创建完表后,添加自动增长。
    代码语言:javascript
    复制
    ALTER TABLE stu MODIFY id INT AUTO_INCREMENT;
代码语言:javascript
复制
CREATE TABLE stu (
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(20)
);

-- 添加数据
INSERT INTO stu(id,NAME) VALUES (1,'露娜');
INSERT INTO stu(id,NAME) VALUES (NULL,'貂蝉');
5. 外键约束:foreign key
  1. 概述:
    • 让表与表产生关系,从而保证数据的正确性。
  2. 在创建表时,添加外键
代码语言:javascript
复制
* 语法:
create table 表名 (
    ...
    外键列,
    constraint 外键名称 foreign key (外键列名称) references 主表名称(主表列名称)
);
  1. 删除外键
代码语言:javascript
复制
alter table 表名 drop foreign key 外键名称;
  1. 创建表之后,添加外键
  • 示例:
代码语言:javascript
复制
-- 主表必须先创建,否则外键创建失败
CREATE TABLE sch (
    id INT PRIMARY KEY AUTO_INCREMENT,
    address VARCHAR(20)  -- 地址
);

CREATE TABLE stu (
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(20),
    address_id INT, -- 外键列
    -- constraint 外键名称 foreign key (外键列名称) references 主表名称(主表列名称)
    CONSTRAINT stu_sch_fy FOREIGN KEY (address_id) REFERENCES sch(id)
);

INSERT INTO sch(id,address) VALUES (1,'北京');
INSERT INTO sch(id,address) VALUES (NULL,'西安');

INSERT INTO stu(NAME,address_id) VALUES ('张三',1),('露娜',1),('貂蝉',2),('吕布',2),('赵云',1);
-- --------------------------分隔符-------------------------------------------

-- 删除外键
ALTER TABLE stu DROP FOREIGN KEY stu_sch_fy;

-- 创建完表后再添加外键
ALTER TABLE stu ADD CONSTRAINT stu_sch_fy FOREIGN KEY (address_id) REFERENCES sch(id);
代码语言:javascript
复制
alter table 表名 add constraint 外键名称 foreign key (外键字段名称) references 主表名称(主列表名称);
6.级联操作
  • 添加级联操作:
代码语言:javascript
复制
* 语法:
alter table 表名 add constraint 外键名称
    foreign key (外键字段名称) references 主表名称(主表列名称) on update cascade on delete cascade;
  • 分类:
    1. 级联更新:on update cascade
    2. 级联删除:on delete cascade

* 数据库的备份和还原

  1. 命令行:
    • 语法:
      • 备份:mysqldump -u用户名 -p密码 要备份的数据库名 > 保存的路径
      • 还原:
        1. 登录数据库
        2. 创建数据库
        3. 使用数据库;
        4. 执行文件:source 文件路径;
  2. 图形化工具: $$ 百度查询 $$

二、数据库的设计

1. 多表之间的关系:

1. 一对一:

  • 如:人和身份证
  • 分析:一个人只有一个身份证,一个身份证只能对应一个人
  • 实现方式:可以在任意一方添加唯一外键指向另一方的主键。

2.一对多(多对一):

  • 如:部门和员工
  • 分析:一个部门有多个员工,一个员工只能对应一个部门
  • 实现方式:在多的一方建立外键,指向一的一方的主键。

3. 多对多:

  • 如:学生和课程
  • 分析:一个学生可以选择很多门课程,一个课程也可以被很多学生选择
  • 实现方式: 多对多关系实现需要借助第三张中间表; 中间表至少包含两个字段,这两个字段作为第三张表的外键,分别指向两张表的主键。

4.联合主键

  • 示例
代码语言:javascript
复制
CREATE TABLE table_uy (
    uid INT , -- 线路id
    yid INT , -- 用户id
    -- 创建复合主键
    PRIMARY KEY(uid,yid), -- 联合主键
    -- 分别相互关联对方表的主键
    FOREIGN KEY (uid) REFERENCES tab_yead (yid),
    FOREIGN KEY (yid) REFERENCES tab_user (uid)
    
);

2. 数据库设计的范式:

1. 概述:

设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。 目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)

2. 函数依赖:

  1. 函数依赖:A–>B,如果通过A属性(属性组)的值,可以确定唯一B属 性的值,则称B依赖于A; ​ 例如:学号 –> 姓名
  2. 完全函数依赖:A –> B,如果A是一个属性组,则B属性值的确定需 要依赖于A属性组中所有的属性值; ​ 例如:(学号,课程名称) –> 分数
  3. 部分函数依赖:A –> B,如果A是一个属性组,则B属性值的确定 只需要依赖于A属性组中某一些值即可; ​ 例如:(学号,课程名称) –> 姓名
  4. 传递函数依赖:A–>B,B –> C,如果通过A属性(属性组)的值,可 以确定唯一B属性的值,在通过B属性(属性组)的值可 以确定唯一C属性的值,则称C传递函数依赖于A; ​ 例如:学号 –> 系名,系名 –> 系主任
  5. 码:如果在一张表中,一个属性或属性组,被其他所有属性完全 依赖,则称这个属性(属性组)为该表的码。 ​ 例如:该表中码为:(学号,课程名称) * 主属性:码属性组中所有的属性 * 非主属性:除过码属性组的属性

3. 三大范式:

  • 第一范式(1NF):每一列都是不可分割的院子数据项(只要能表能出来,都符合第一范式);
  • 第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于码(在1NF基础上消除非主属性对主码的函数部分依赖);
  • 第三范式(3NF):在2NF基础上,任何非主属性不能依赖于其它非主属性(在2NF基础上消除传递依赖)。

三、多表查询

1. 笛卡尔积:

  • 有两个集合A,B,取这两个集合的所有组成情况,
  • 要完成多表查询,需要消除无用的数据

2. 多表查询的分类:

  • 内连接查询
  • 外连接查询
  • 子查询
  • 建表:
代码语言:javascript
复制
# 创建部门表
CREATE TABLE dept (
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(20)
);
INSERT INTO dept(NAME) VALUES ('开发部'),('市场部'),('财务部');

# 创建员工表
CREATE TABLE emp (
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(10),
    sex CHAR(1),
    salary DOUBLE,
    jion_date DATE,
    dept_id INT,
    FOREIGN KEY (dept_id) REFERENCES dept(id) -- 外键,关联部门表(部门表的主键)
);

INSERT INTO emp (NAME,sex,salary,jion_date,dept_id) VALUES ('孙悟空','男',7200,'2013-02-24',1),
('猪八戒','男',3600,'2010-12-02',2),
('唐曾','男',9600,'2008-08-08',2),
('白骨精','女',5000,'2015-10-17',3),
('蜘蛛精','女',4500,'2011-03-04',1);

3. 内连接查询:

1. 隐式内连接

  • 使用where条件消除无用数据
  • 示例:
代码语言:javascript
复制
-- 查询所有员工信息和对应的部门信息
SELECT * FROM emp,dept WHERE emp.dept_id = dept.id; 

-- 查询员工表的名称,性别。部门表的名称
SELECT emp.name,emp.sex,dept.name FROM emp,dept WHERE emp.dept_id = dept.id;

-- 标准写法
SELECT
    a.name, -- 员工表姓名
    a.sex, -- 员工表性别
    b.name -- 部门表姓名
FROM 
    emp a,
    dept b
WHERE 
    a.dept_id = b.id

2. 显示内连接:

代码语言:javascript
复制
* 语法:
    select 字段列表 from 表名1 [inner] jion 表名2 on 条件
    
* 示例:
-- 查询所有员工信息和对应的部门信息
SELECT * FROM emp INNER JOIN dept ON emp.dept_id = dept.id;
SELECT * FROM emp JOIN dept ON emp.dept_id = dept.id; -- inner可以省略

3. 内连接查询注意事项:

  1. 从哪些表中查询数据;
  2. 条件是什么;
  3. 查询哪些字段

4. 外连接查询:

1. 左外连接:

  • 语法 select 字段列表 from 表1 left [outer] join 表2 on 条件;
  • 查询的是左表所有数据以及其交集部分。
  • 示例:
image-20200407092653730
image-20200407092653730
代码语言:javascript
复制
-- 左外连接
SELECT * FROM emp LEFT OUTER JOIN dept ON emp.dept_id = dept.id;

2. 右外连接:

  • 语法: select 字段列表 from 表1 right [outer] join 表2 on 条件;
  • 查询的是右表所有数据以及其交集部分
  • 示例:
image-20200407095702913
image-20200407095702913
代码语言:javascript
复制
-- 右外连接
SELECT * FROM dept RIGHT OUTER JOIN emp ON emp.dept_id = dept.id;

5. 子查询:

1. 子查询的基本查询:

  • 概念:查询中嵌套查询,成嵌套查询为子查询。
  • 示例:
代码语言:javascript
复制
-- 查询最高工资员工信息
-- 1.先查询最高工资是多少
SELECT MAX(salary) FROM emp;

-- 2.查询员工信息,工资等于9600的
SELECT * FROM emp WHERE salary = 9600;

-- ----------------------------------------
-- 利用子查询完成
SELECT * FROM emp WHERE salary = (SELECT MAX(salary) FROM emp);

2.子查询的不同情况:

1. 子查询的结果是单行单列的:
  • 子查询可以作为条件,使用运算符去判断。 运算符:> , <, >=, <=, =
  • 示例:
代码语言:javascript
复制
-- 查询工资小于平均工资的员工信息
SELECT * FROM emp WHERE salary < (SELECT AVG(salary) FROM emp);
2. 子查询的结果是多行单列的:
  • 子查询可以作为条件,使用运算符in来判断
  • 示例:
代码语言:javascript
复制
-- 查询财务部和市场部的所有员工信息
SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部';
SELECT * FROM emp WHERE dept_id = 2 OR dept_id = 3;
SELECT * FROM emp WHERE dept_id IN (2,3);
-- 利用子查询解决
SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部');
3. 子查询的结果是多行多列的:
代码语言:javascript
复制
* 子查询可以作为一张虚拟表参与查询

-- 查询入职时间在2011-11-11之后的员工信息和部门信息
SELECT 
    * 
FROM 
    dept a,
    (SELECT * FROM emp WHERE jion_date > '2011-11-11') b
WHERE 
    b.dept_id = a.id;
    
-- ---------------------------------------------------
-- 普通内查询
SELECT * FROM emp a,dept b WHERE a.dept_id = b.id AND a.jion_date > '2011-11-11';

四、事务

1. 事务的基本概念

  1. 概念: 如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。
  2. 操作:
    1. 开启事务:start tansacton
    2. 回滚:rollback
    3. 提交:commit
  • 示例:
代码语言:javascript
复制
CREATE TABLE zhuangzhang (
    NAME VARCHAR(20),
    money INT
);
INSERT INTO zhuangzhang(NAME,money) VALUES ('张三',1000),('李四',1000);


-- 开启事务
START TRANSACTION;
-- 张三给李四转账
UPDATE zhuangzhang SET money = money - 500 WHERE NAME = '张三';

异常来啦

UPDATE zhuangzhang SET money = money + 500 WHERE NAME = '李四';

-- 发现没有问题,提交事务
COMMIT


-- 发现出问题了,回滚事务
ROLLBACK

2. 事务的四大特征

  1. 原子性:是不可能分割的最小操作单位,要么同时成功,要么同时失败;
  2. 持久性:当事务提交或回滚后,数据后会持久化的保存数据;
  3. 隔离性:多个事务之间,相互独立;
  4. 一致性:事务操作前后,数据总量不变。

3. 事务的隔离级别(了解)

1. 概念:

​ 多个事务之间隔离的,相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题。

2. 存在问题:

  1. 脏读:一个事务,读取到另一个事务中没有提交的数据;
  2. 不可重复读(虚读):早同一个事务中,两次读取到的数据不一样;
  3. 幻读:一个事务操作(DML)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。

3. 隔离级别:

  1. read uncommitted:读未提交
    • 产生的问题:脏读、不可重复读、幻读
  2. read committed:读已提交 (Oracle默认级别)
    • 产生的问题:不可重复读、幻读
  3. repeatable read:可重复读 (MySQL默认级别)
    • 产生的问题:幻读
  4. serializable:串行化
    • 可以解决所有的问题
  • 注意: 隔离级别从小到大安全性越来越高,但是效率越来越低。
代码语言:javascript
复制
* 数据库查询隔离级别:
    select @@tx_isolation;
    
* 数据库设置隔离级别:
    set global transaction isolation level 级别字符串;

4. MySQL数据库中事务默认自动提交

1. 事务提交的两种方式:

  • 自动提交:
    • mysql就是自动提交的;
    • 一条DML(增删改)语句会自动提交一次事务。
  • 手动提交:
    • Oracle数据库默认是手动提交事务;
    • 需要先开启事务,再提交。

2. 修改事务的默认提交方式:

  • 查看事务的默认提交方式
    • select @@autocommit; 1代表自动提交,0代表手动提交
  • 修改默认提交方式:
    • set @@autocommit = 0;

五、DCL:管理用户、授权

1. 管理用户

1. 添加用户:

create user ‘用户名’ @’主机名’ identified by ‘密码’;

2. 删除用户:

drop user ‘用户名‘@’主机名’;

3. 修改用户密码:

方式1:update user set password = password(‘新密码’) where user = ‘用户名’;

方式2:set password for ‘用户名’ @’主机名’ = password(‘新密码’);

4. mysql中忘记了root用户的密码?

  1. cmd –> net stop mysql 停止mysql服务
    • 需要管理员运行cmd
  2. 使用无验证方式启动mysql:mysqld –skip-grant-tables
  3. 打开新的cmd窗口,直接输入mysql命令,敲回车,就可以登录成功
  4. use mysql
  5. update user set passwprd = password(‘你的新密码’) where user = ‘root’;
  6. 关闭两个窗口
  7. 打开任务管理器,手动结束mysqld.exe的进程
  8. 启动mysql服务
  9. 使用新密码登录

5. 查询用户:

  • 1.切换到mysql数据库 use mysql;
  • 2.查询user表 select * from user;
  • 通配符: % 表示可以在任意主机使用用户登录数据库

2. 权限管理

1. 查询权限

show grants for ‘用户名‘@’主机名’;

2. 授予权限

grant 权限列表 on 数据库名.表名 to ‘用户名‘@’主机名’; 给哪位用户授权什么权限,在什么数据库的什么表上

代码语言:javascript
复制
给某位用户授予所有权限,在任意数据库任意表上
grant all on *.* to '用户名'@'localhost';

3. 撤销权限

revoke 权限列表 on 数据库名.表名 from ‘用户名‘@’主机名’;

六、JDBC

1. 概述:

  • 概念:Java DataBase ConnectIvity ,Java 数据库连接,Java语言操作数据库。
  • JDBC本质:其实是官方(SUN公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

2. 步骤

代码语言:javascript
复制
*        //1. 导入驱动jar包
*        //2. 注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver"); // mysql 5版本之后可以省略
*        //3. 获取数据库连接对象
        //Connection conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "lxj521..");
        Connection conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "lxj521..");//省略本机名和IP写法
*        //4. 定义sql语句
        String sql = "update zhuangzhang set money = 1000";
*        //5. 获取执行sql的对象     Statement
        Statement statement = conn.createStatement();
*        //6. 执行sql
        int count = statement.executeUpdate(sql);
*        //7. 处理结果
        System.out.println(count);
*        //8. 释放资源
        statement.close();
        conn.close();

3.详解各个对象:

1. DriverManager:驱动管理对象

代码语言:javascript
复制
* 功能:
    1. 注册驱动:告诉程序该使用哪一个数据库驱动jar
    static void registerDriver(Driver driver):注册与给定的驱动程序DriverManager
    写代码使用:Class.forName("com.mysql.jdbc.Driver")
    
    通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块.
* 注意:mysql 5之后的驱动jar包可以省略注册驱动的步骤。但建议还是写上。

    2. 获取数据库连接
    * 方法:static Connection getConnection(String url,String user,String password)
    * 参数:
        * url:指定连接的路径
            * 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
            * 例子:jdbc:mysql://localhost:3306/db3
            * 细节:如果连接的是本机mysql服务器,并且mysql服务器默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称
        * user:用户名
        * password:密码

2. Connection:数据库连接对象

代码语言:javascript
复制
* 功能:
    1. 获取执行sql的对象
        * Statement createStatement()
        * PreparedStatement preparedStatement(String sql)
    2. 管理事务:
        * 开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事务
        * 提交事务:commit()
        * 回滚事务:rollback()

3. Statement:执行sql的对象

代码语言:javascript
复制
* 执行sql
    1. boolean execute(String sql):可以执行任意的sql(了解)
    2. int executeUpdate(String sql):执行DML(insert,update,delete)语句,DDL(create,alter,drop)语句
        * 返回值:影响的行数,可以通过这个影响地行数判断DML是否执行成功,返回值>0的则执行成功,反之,则失败。
    3. ResultSet executeQuery(String sql):执行DQL(select)语句。
        * 返回值为结果集对象。

4. ResultSet:结果集对象

代码语言:javascript
复制
* next():游标向下移动一行
* getXxx(参数):获取数据
    * Xxx:代表数据类型   如:int:getInt(), String:getString()
    * 参数:
        1.int :代表列的编号,从1开始。  如:getString(1)
        2.String:代表列名称。 如:getDoble("balance")
  • 示例:
代码语言:javascript
复制
public class Demo05 {
    public static void main(String[] args) {
        ResultSet resultSet = null;
        Statement statement = null;
        Connection conn = null;
        try {
            //1.注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.获取数据库连接对象
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "lxj521..");
            //3.定义sql
            String sql = "select * from zhuangzhang";
            //4.获取sql执行对象
            statement = conn.createStatement();
            //5.执行sql
            resultSet = statement.executeQuery(sql);
            //6.处理结果
            //6.1 游标向下移动一行:因为要查询第一行的数据
            resultSet.next();
            //6.2 获取数据
            String name = resultSet.getString(1);
            double money = resultSet.getDouble("money");
            //7.处理结果
            System.out.println(name + "===" + money);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            ////8. 释放资源
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
附加:ResultSet遍历
代码语言:javascript
复制
* boolean next():游标向下移动一行,判断当前是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true

* 利用while循环遍历
while (rs.next()) {
                String name = rs.getString(1);
                double money = rs.getDouble("money");
                System.out.println(name + "---" + money);
            }
练习:查询emp表中所有数据
image-20200408185749935
image-20200408185749935
image-20200408185812605
image-20200408185812605
  • 先创建一个emp类
代码语言:javascript
复制
public class emp {
    private int id;
    private String name;
    private String sex;
    private double salary;
    private Date jion_date;
    private int dept_id;

    public emp(int id, String name, String sex, double salary, Date jion_date, int dept_id) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.salary = salary;
        this.jion_date = jion_date;
        this.dept_id = dept_id;
    }

    public emp() {

    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public Date getJion_date(Date jion_date) {
        return this.jion_date;
    }

    public void setJion_date(Date jion_date) {
        this.jion_date = jion_date;
    }

    public int getDept_id() {
        return dept_id;
    }

    public void setDept_id(int dept_id) {
        this.dept_id = dept_id;
    }

    @Override
    public String toString() {
        return "emp{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sex=" + sex +
                ", salary=" + salary +
                ", jion_date=" + jion_date +
                ", dept_id=" + dept_id +
                '}';
    }
}
/*
* 提示:该行代码过长,系统自动注释不进行高亮。一键复制会移除系统注释 
* <!--hexoPostRenderEscape:<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line"></span><br><span class="line">  * 再创建一个主类,调用emp方法</span><br><span class="line"></span><br><span class="line">&#96;&#96;&#96;java</span><br><span class="line">public class Demo07 &#123;</span><br><span class="line">    public static void main(String[] args) &#123;</span><br><span class="line">        List&lt;emp&gt; list &#x3D; new Demo07().findAll();</span><br><span class="line">        System.out.println(list);</span><br><span class="line">        System.out.println(list.size());</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    public List&lt;emp&gt; findAll() &#123;</span><br><span class="line">        ResultSet rs &#x3D; null;</span><br><span class="line">        Statement statement &#x3D; null;</span><br><span class="line">        Connection conn &#x3D; null;</span><br><span class="line"></span><br><span class="line">        List&lt;emp&gt; list &#x3D; null;</span><br><span class="line">        try &#123;</span><br><span class="line">            &#x2F;&#x2F;1.注册驱动</span><br><span class="line">            Class.forName(&quot;com.mysql.cj.jdbc.Driver&quot;);</span><br><span class="line">            &#x2F;&#x2F;2.获取连接数据库对象</span><br><span class="line">            conn &#x3D; DriverManager.getConnection(&quot;jdbc:mysql:&#x2F;&#x2F;&#x2F;db2&quot;, &quot;root&quot;, &quot;lxj521..&quot;);</span><br><span class="line">            &#x2F;&#x2F;3.定义sql</span><br><span class="line">            String sql &#x3D; &quot;select * from emp&quot;;</span><br><span class="line">            &#x2F;&#x2F;4.获取处理sql对象</span><br><span class="line">            statement &#x3D; conn.createStatement();</span><br><span class="line">            &#x2F;&#x2F;5.处理sql</span><br><span class="line">            rs &#x3D; statement.executeQuery(sql);</span><br><span class="line">            &#x2F;&#x2F;6.处理结果</span><br><span class="line">            emp emp &#x3D; null;</span><br><span class="line">            list &#x3D; new ArrayList&lt;emp&gt;();</span><br><span class="line">            while (rs.next()) &#123;</span><br><span class="line">                int id &#x3D; rs.getInt(&quot;id&quot;);</span><br><span class="line">                String name &#x3D; rs.getString(&quot;name&quot;);</span><br><span class="line">                String sex &#x3D; rs.getString(&quot;sex&quot;);</span><br><span class="line">                double salary &#x3D; rs.getDouble(&quot;salary&quot;);</span><br><span class="line">                Date jion_date &#x3D; rs.getDate(&quot;jion_date&quot;);</span><br><span class="line">                int dept_id &#x3D; rs.getInt(&quot;dept_id&quot;);</span><br><span class="line"></span><br><span class="line">                &#x2F;&#x2F;创建emp对象,并赋值</span><br><span class="line">                emp &#x3D; new emp();</span><br><span class="line">                emp.setId(id);</span><br><span class="line">                emp.setName(name);</span><br><span class="line">                emp.setSex(sex);</span><br><span class="line">                emp.setSalary(salary);</span><br><span class="line">                emp.getJion_date(jion_date);</span><br><span class="line">                emp.setDept_id(dept_id);</span><br><span class="line"></span><br><span class="line">                &#x2F;&#x2F;装载集合</span><br><span class="line">                list.add(emp);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; catch (ClassNotFoundException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125; catch (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125; finally &#123;</span><br><span class="line">            if (rs !&#x3D; null) &#123;</span><br><span class="line">                try &#123;</span><br><span class="line">                    rs.close();</span><br><span class="line">                &#125; catch (SQLException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            if (statement !&#x3D; null) &#123;</span><br><span class="line">                try &#123;</span><br><span class="line">                    statement.close();</span><br><span class="line">                &#125; catch (SQLException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            if (conn!&#x3D;null) &#123;</span><br><span class="line">                try &#123;</span><br><span class="line">                    conn.close();</span><br><span class="line">                &#125; catch (SQLException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        return list;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>:hexoPostRenderEscape-->
*/

5. PreparedStatement:执行sql的对象

1. SQL注入问题:
代码语言:javascript
复制
在拼接sql时,有一些sql的特殊关键字参与字符串的拼接,会造成安全性问题;
* 1.输入用户随便,输入密码:a' or 'a' = 'a
  2.sql:select * from user where username = "ahdahal" and password = a' or 'a' = 'a
2. 解决sql注入问题:
  • 使用PreparedStatement对象来解决
3. 预编译的SQL:
  • 参数使用 ? 作为占位符
*4. 步骤:**
代码语言:javascript
复制
1.导入驱动jar包;
2.注册驱动;
3.获取数据库连接对象 Connection
4.定义sql
    * 注意:sql的参数使用?作为占位符。
      如:select * from user where username = ? and password = ?;
5.获取执行sql语句的对象    PreparedStatement
    * Connection.prepareSttement(String sql)
6.给?赋值:
    * 方法:setXxx(参数1,参数2)
        * 参数1:?的位置编号 从1 开始
        * 参数2:?的值
7.执行sql,接受返回结果,不需要传递sql语句
8.处理结果
9.释放资源
  • 示例:
代码语言:javascript
复制
public class Demo02 {
    public static void main(String[] args) {


        //键盘录入
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = sc.nextLine();
        System.out.println("请输入密码:");
        String password = sc.nextLine();
        //调用对象
        boolean flag = new Demo02().login2(username, password);
        //判断结果
        if (flag) {
            System.out.println("登录成功");
        } else {
            System.out.println("用户名或者密码错误");
        }
    }

    //登录方法
    public boolean login2(String username,String password) {
        if ((username == null) || (password == null)) {
            return false;
        }

        //连接数据库判断是否登录成功
        Connection conn = null;
        PreparedStatement pstem =null;
        ResultSet rs = null;
        try {
            //1.获取连接数据库对象
            conn = JDBCUtils.getConnection();
            //2.定义sql
            String sql = "select * from user where username = ? and password = ?";
            //3.获取处理sql对象
             pstem = conn.prepareStatement(sql);
             //给?赋值
            pstem.setString(1,username);
            pstem.setString(2,password);
            //4.执行查询sql,不需要传递sql
            rs = pstem.executeQuery();
            //5.判断
            return rs.next();//如果有下一行,则返回true
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(rs,pstem,conn);
        }

        return false;
    }
}
5.注意:
  • 后期都会使用PreparedStatement来完成增删改查的所有操作
    • 1、可以防止SQL注入;
    • 2、效率更高

七、JDBC工具类:JDBCUtils

  • 目的:简化书写
  • 分析:
    • 1、注册驱动也抽取;
    • 2、抽取一个方法获取连接对象
代码语言:javascript
复制
* 需求:不想传递参数(麻烦),还得保证工具类的通用性。
* 解决:配置文件:
    * 创建 jdbc.properties    文件
          url = 
          user = 
          password = 
          driver = 
* 示例:
url=jdbc:mysql:///db2
user=root
password=lxj521..
driver=com.mysql.cj.jdbc.Driver
  • 创建工具类:
代码语言:javascript
复制
* 首先创建名为JDBCUtils.java  文件 

/*
 * JDBC工具类
 * */

import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Collection;
import java.util.Properties;

public class JDBCUtils {
    private static String url;
    private static String user;
    private static String password;
    private static String driver;

    /*
    * 文件的读取,只需要读取一次即可拿到这些值。只用静态代码块
    * */
    static {
        //读取资源文件,获取值

        try {
            //1.创建Properties集合类
            Properties pro = new Properties();

            //获取src路径下的文件的方式:ClassLoader 类加载器
            ClassLoader classLoader = JDBCUtils.class.getClassLoader();
            URL resource = classLoader.getResource("jdbc.properties");
            String path = resource.getPath();
            //System.out.println(path);

            //2.加载文件
//            pro.load(new FileReader("src/jdbc.properties"));
            pro.load(new FileReader(path));
            //3.获取数据,赋值
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
            //4.注册驱动
            Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /*
    * 获取连接
    * @return 连接对象
    * */
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,user,password);
    }

    /*
    * 释放资源
    * */
    public static void close(Statement statement,Connection conn) {
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    //释放资源,重载
    public static void close(ResultSet rs,Statement statement,Connection conn) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn!=null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 调用工具示例:
代码语言:javascript
复制
public class Demo {
    public static void main(String[] args) {
        List<emp> list = new Demo().findAll();
        System.out.println(list);
        System.out.println(list.size());

    }

    public List<emp> findAll() {
        ResultSet rs = null;
        Statement statement = null;
        Connection conn = null;

        List<emp> list = null;
        try {
            //1.注册驱动
//            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.获取连接数据库对象
//            conn = DriverManager.getConnection("jdbc:mysql:///db2", "root", "lxj521..");
            conn = JDBCUtils.getConnection();
            //3.定义sql
            String sql = "select * from emp";
            //4.获取处理sql对象
            statement = conn.createStatement();
            //5.处理sql
            rs = statement.executeQuery(sql);
            //6.处理结果
            emp emp = null;
            list = new ArrayList<emp>();
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String sex = rs.getString("sex");
                double salary = rs.getDouble("salary");
                Date jion_date = rs.getDate("jion_date");
                int dept_id = rs.getInt("dept_id");

                //创建emp对象,并赋值
                emp = new emp();
                emp.setId(id);
                emp.setName(name);
                emp.setSex(sex);
                emp.setSalary(salary);
                emp.getJion_date(jion_date);
                emp.setDept_id(dept_id);

                //装载集合
                list.add(emp);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //释放资源
            JDBCUtils.close(rs, statement, conn);
        }
        return list;
    }
}

八、JDBC管理事务

1. 事务:

一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。

2. 操作:

  1. 开启事务
  2. 提交事务
  3. 回滚事务

3. 使用Connection对象来管理事务

代码语言:javascript
复制
* 开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事务;
        *   在执行sql之前开启事务
* 提交事务:commit()
        *   当所有sql都执行完提交事务
* 回滚事务:rollback()
        *   在catch中回滚事务
  • 示例:
  • 发生异常后,如果数据没有变化,则说明我们管理事务成功,反之则失败。
代码语言:javascript
复制
public class Demo3 {
    public static void main(String[] args) {
        PreparedStatement pstm1 = null;
        PreparedStatement pstm2 = null;
        Connection conn = null;
        try {
            //1.注册驱动
            conn = JDBCUtils.getConnection();

            //开启事务
            conn.setAutoCommit(false);

            //2.定义sql
            String sql1 = "update zhuangzhang set money = money - ? where name = ?";
            String sql2 = "update zhuangzhang set money = money + ? where name = ?";
            //3.获取处理sql对象
            pstm1 = conn.prepareStatement(sql1);
            pstm2 = conn.prepareStatement(sql2);
            //4.给?赋值
            pstm1.setDouble(1, 500);
            pstm1.setString(2, "张三");

            pstm2.setDouble(1, 500);
            pstm2.setString(2, "李四");
            //5.处理sql,不需要获取sql
            pstm1.executeUpdate();

            //手动设置异常
            int i = 3 / 0;

            pstm2.executeUpdate();
        } catch (SQLException e) {
            //回滚事务
            try {
                if (conn != null) {
                    conn.rollback();
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            //释放资源
            JDBCUtils.close(pstm1, conn);
            JDBCUtils.close(pstm2, null);
        }
    }
}

九、数据库连接池

1. 概念:

其实就是一个容器(集合),存放数据库连接的容器。

当系统初始化好后,容器被创建,容器中会申请宁一些连接对象,当用户来访问数据库时,从容器中中获取连接对象,榕湖访问完之后,会将连接对象归还给容器。

2. 好处:

  1. 节约资源;
  2. 用户访问高效。

3. 实现:

1. 标准接口:DataSource javax.sql包下的

代码语言:javascript
复制
方法:
    * 获取连接:getConnection()
    * 归还连接:Connection.close().如果连接对象Connection是从连接池获取的,那么调用Connection.close()方法,则不会再关闭连接了,而是归还连接。

2. 连接池种类:

  • 一般我们不会去实现它,有数据库厂商来实现
    • 1、C3P0:数据库连接池技术;
    • 2、Druid:数据库连接池实现技术,由阿里巴巴提供的。

4.C3P0

代码语言:javascript
复制
* 步骤:
    1.导入jar包(两个)c3p0-0.9.5.5-sources.jar和mchange-commons-java-0.2.19-sources.jar;
        * 不要忘记导入数据库驱动jar包:mysql-connector-java-8.0.19.jar
    2.定义配置文件:
        * 名称:c3p0.properties 或者 c3p0-config.xml
        * 路径:直接将文件放在src目录下即可。
    3.创建核心对象:
        数据库连接池对象 ComboPooledDataSource
    4.获取连接:getConnection

5.Druid

1. 步骤

代码语言:javascript
复制
* 步骤:
        //1.导入jar包     druid-1.1.18.jar
        //2.定义配置文件
        * 是properties形式的
        * 可以叫任意名称,可以放在任意目录下

        //3.加载配置文件    Properties
        Properties pro = new Properties();                                    InputStreamis=DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
        pro.load(is);

        //4.获取连接池对象:通过工厂来获取  DruidDataSourceFactory
        DataSource ds = DruidDataSourceFactory.createDataSource(pro);

        //5.获取连接    getConnection
        Connection conn = ds.getConnection();
        System.out.println(conn);
  • 配置文件:druid.properties
代码语言:javascript
复制
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql:///db3
username=root
password=lxj521..
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000

2. druid工具类:

代码语言:javascript
复制
1.定义一个类:JDBCUtils
2.提供静态代码块加载配置文件,初始化连接池对象
3.提供方法
    1.获取连接方法:通过数据库连接池获取连接;
    2.释放资源;
    3.获取连接池的方法。
  • 创建工具类:JDBCUtils.java
代码语言:javascript
复制
public class JDBCUtils {

    //1.定义成员变量 DataSours
    private static DataSource ds;

    static {

        try {
            //1.记载配置文件
            Properties prop = new Properties();
            prop.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            //2.获取DataSource
            ds = DruidDataSourceFactory.createDataSource(prop);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //获取连接
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    //释放资源
    public static void close(Statement statement,Connection conn) {
//        if (statement != null) {
//            try {
//                statement.close();
//            } catch (SQLException e) {
//                e.printStackTrace();
//            }
//        }
//        if (conn != null) {
//            try {
//                conn.close(); //归还连接
//            } catch (SQLException e) {
//                e.printStackTrace();
//            }
//        }
        close(null,statement,conn);
    }

    public static void close(ResultSet resultSet,Statement statement, Connection conn) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close(); //归还连接
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    //获取连接池方法
    public static DataSource getDataSource() {
        return ds;
    }
}
  • 示例:给zhuangzhang表里添加数据:
代码语言:javascript
复制
public class Demo02 {
    public static void main(String[] args) {

        Connection conn = null;
        PreparedStatement ps = null;
        try {
            //1.获取连接:
            conn = JDBCUtils.getConnection();
            //2.定义sql:
            String sql = "insert into zhuangzhang value (?,?)";
            //3.获取处理sql对象
            ps = conn.prepareStatement(sql);
            //4.给?赋值
            ps.setString(1, "王五");
            ps.setDouble(2, 2000);
            //5.执行sql
            int count = ps.executeUpdate();
            System.out.println(count);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //6.释放资源
            JDBCUtils.close(ps, conn);
        }
    }
}

十、JDBCTemplate

spring JDBC

  • Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发
  • 步骤:
  • 1.导入jar包 2.创建JDBCTemplate对象,依赖于数据源DataSource * JdbcTemplate template = new JdbcTemplate(ds); 3.调用JdbcTemplate的方法来完成CRUD的操作: * update():执行DML语句。增删改 * queryForMap():查询结果将结果集封装为map集合 * queryForList():查询结果将结果集封装为list集合 * query():查询结果,将结果封装为JavaBean对象 * queryForObject:查询结果,将结果封装为对象

https://repo.spring.io/release/org/springframework/

文章作者: silentcow

文章链接: http://silentcow.cn/2020/08/06/MySQL%E4%B8%8EJDBC%E7%B2%BE%E8%AE%B2%E7%AC%94%E8%AE%B0/

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-08-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、数据库
    • 1.数据库的基本概念
      • 1.数据库的英文单词:
      • 2. 什么是数据库?
      • 3 .数据库的特点:
      • 4. MySQL的安装和卸载
      • 5. MySQL的登录和退出
    • 2. SQL
      • 1.什么是SQL?
      • 2. SQL通用语法
      • 3. SQL分类
    • 3. DDL:操作数据库、表
      • 1. 操作数据库:CRUD
      • 2.操作表:
    • 4. DML: 增删改表中数据
      • 1. 添加数据:
      • 2. 删除数据:
      • 3. 修改数据:
    • 5. DQL: 查询表中的记录
      • 1. 语法:
      • 2. 基础查询:
      • 3. 条件查询
      • 4. 排序查询
      • 5. 聚合函数
      • 6. 分组查询
      • 7. 分页查询
    • 8. 约束
      • 1. 概念和分类
      • 2. 非空约束:not null
      • 3. 唯一约束:UNIQUE
      • 4. 主键约束:primary key
    • * 数据库的备份和还原
    • 二、数据库的设计
      • 1. 多表之间的关系:
        • 1. 一对一:
        • 2.一对多(多对一):
        • 3. 多对多:
        • 4.联合主键
      • 2. 数据库设计的范式:
        • 1. 概述:
        • 2. 函数依赖:
        • 3. 三大范式:
    • 三、多表查询
      • 1. 笛卡尔积:
        • 2. 多表查询的分类:
          • 3. 内连接查询:
            • 1. 隐式内连接
            • 2. 显示内连接:
            • 3. 内连接查询注意事项:
          • 4. 外连接查询:
            • 1. 左外连接:
            • 2. 右外连接:
          • 5. 子查询:
            • 1. 子查询的基本查询:
            • 2.子查询的不同情况:
        • 四、事务
          • 1. 事务的基本概念
            • 2. 事务的四大特征
              • 3. 事务的隔离级别(了解)
                • 1. 概念:
                • 2. 存在问题:
                • 3. 隔离级别:
              • 4. MySQL数据库中事务默认自动提交
                • 1. 事务提交的两种方式:
                • 2. 修改事务的默认提交方式:
            • 五、DCL:管理用户、授权
              • 1. 管理用户
                • 1. 添加用户:
                • 2. 删除用户:
                • 3. 修改用户密码:
                • 4. mysql中忘记了root用户的密码?
                • 5. 查询用户:
              • 2. 权限管理
                • 1. 查询权限
                • 2. 授予权限
                • 3. 撤销权限
            • 六、JDBC
              • 1. 概述:
                • 2. 步骤
                  • 3.详解各个对象:
                    • 1. DriverManager:驱动管理对象
                    • 2. Connection:数据库连接对象
                    • 3. Statement:执行sql的对象
                    • 4. ResultSet:结果集对象
                    • 5. PreparedStatement:执行sql的对象
                • 七、JDBC工具类:JDBCUtils
                • 八、JDBC管理事务
                  • 1. 事务:
                    • 2. 操作:
                      • 3. 使用Connection对象来管理事务
                      • 九、数据库连接池
                        • 1. 概念:
                          • 2. 好处:
                            • 3. 实现:
                              • 1. 标准接口:DataSource javax.sql包下的
                              • 2. 连接池种类:
                            • 4.C3P0
                              • 5.Druid
                                • 1. 步骤
                                • 2. druid工具类:
                            • 十、JDBCTemplate
                            相关产品与服务
                            云数据库 SQL Server
                            腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
                            领券
                            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档