mysql

1、初始MySQL

javaEE:企业级java开放 Web

前端(页面:展示,数据!)

后台(练级点:连接数据库JBDC,链接前端(控制,控制视图跳转,给前端传递数据))

数据库(存数据,Txt,Excel,word)

只会代码,学号数据库--->混饭吃
操作系统,数据结构与算法--->不错的程序猿
离散数学,数字电路,体系结构,编译原理 + 实战经验---->高级的程序员

1.1、什么是数据库

数据库(DB database)

概念:数据仓库,软件,安装在操作系统(window,linux,mac、、、、)之上 SQL 可以存储数据

作用:存储数据,管理数据

1.2、数据库分类

关系型数据库

  • MySQL,Oralce,Sql Server,DB2 SQLlite
  • 通过表和表之间,行和列之间的关系进行数据的存储

非关系数据库

  • Redis ,MongDB
  • 非关系型数据库,对象存储,通过对象的自身属性来决定

DBMS(数据库管理系统)

  • 数据库的管理软件,科学有效的管理数据,维护和获取数据
  • MySQL,数据库管理系统

2、操作数据库

2.1操作数据库

1、创建数据库

CREATE DATABASE [IF NOT EXISTS] westos;

2、删除数据库

drop database [if exists] westos;

3、使用数据库

-- sql语句的注释符  tab键的上面,如果你的表名或者字段是一个特殊字数就需要使用

4、查看数据库

SHOW DATABASES --查看所有的数据库

2.2、数据库的列类型

数组

  • tinint 十分小的数据 1个字节
  • smallin 较小的数据 2个字节
  • mediumint 中等大小的数据 3个字节
  • int 标注的整数 4个字节 常用的
  • bigint 较大的数据 8个字节
  • float 单精度浮点数 4个字节
  • double 双精度浮点数 8个字节
  • decimal 字符串形式的浮点数 金融计算的时候,一般是使用decimal

字符串

  • char 字符串固定大小的 0~255
  • varchar 可变字符串 0~65525 常用的 相当于String
  • tinytext 微型文本 2^8—1
  • text 文本串 2^16—1 保存大文本

时间日期

  • date YYY-MMM-DD 日期格式
  • time HH:mm:ss 时间格式
  • datatime YYY-MMM-DD HH:mm:ss 最常用的时间格式
  • timestamp 时间戳 1970.1.1 到现在的毫秒级
  • year 年份表示

null

  • 没有值,未知
  • 不要使用null进行运算,结果为null

2.3 数据库的字段属性

Unsigned:

  • 无符号的整数
  • 不能声明为负数

zerofill:

  • 0填充的
  • 不足的数,使用0来填充,

自增:

  • 通常理解为自增,自动在上一条记录的基础上+1(默认)
  • 通常用来设计唯一的主键,
  • 可以自定义设计起始值和步长

非空:not null

  • 假设设置为 not null ,如果不给它复制,就会报错
  • null 如果不填写值,默认就是null

默认:

  • 设置默认的值
  • 设定后不填写,就为设置的值

扩展:

每一个表,都需要以下五个字段
id 主键
`versiion`  乐观锁
is_delate   伪删除
gmt_create  创建时间
gmt_update  修改时间

创建表

CREATE TABLE [IF NOT EXISTS] `表名`(
	·字段名· 列类型 [属性] [索引] [注释],
	·字段名· 列类型 [属性] [索引] [注释],	
	·字段名· 列类型 [属性] [索引] [注释],
	....
	·字段名· 列类型 [属性] [索引] [注释]
	PRIMARY KEY(`自增列`)
)[表类型] [字符集设置] [注释]

常用命令

SHOW CREATE DATABASE school  --查看创建数据库语句
SHOW CREATE TABLE `student`  --查看创建表语句
DESC student   --显示表的结构

2.4 数据表的类型

INNODB   默认使用
MYISAM   以前使用
MYSIAM INNODB
事务支持 不支持 支持
数据行锁定 不支持 支持
外键约束 不支持 支持
全文索引 支持 不支持
表空间大小 较小 较大 约为前者两倍

常规使用操作:

  • MYISAM 节约空间,速度较快
  • INNODB 安全性高,适合事务的处理,夺标多用户操作

所有的数据库文件都存储在data文件下

本质还是文件的存储

MySQL 引擎在物理文件上的区别

  • innoDB 在数据库表中只有一个*.frm文件,以及上级目录下的 ibdata1 文件
  • MYISAM
    • *.frm-----表结构的定义文件
    • *.MYD------数据文件(data)
    • *.MYI -------索引文件(index)

2.5、修改删除表

修改
--修改表名: ALTER TABLE 旧表名  RENAME AS 新表名
ALTER TABLE teacher RENAME AS student

--增加表的字段:ALTER TABLE 表名 ADD 字段名 列属性
ALTER TABLE student ADD age INT(11)

--修改表的字段(重命名,修改约束)
--ALTER TABLE 表名 MODIFY 列名 (修改后的)列属性[]
ALTER TABLE student MODIFY AGE varchar(11)   ---修改约束--->属性
--ALTER TABLE 表名 CHANGE 旧列名 新列名  (可以是新)列属性[]
ALTER TABLE student CHANGE age age1 INT(11)

--删除表的字段;ALTER TABLE 表名 DROP 列名
ALTER TABLE student DROP age1

总结:

  • change :可以修改 列名 和 列的属性 但是无论列名是否修改 都需要两个列名(前后可以相同)
  • modify:只能更改列的属性 但是只需要一次列名
删除
--删除表(如果表存在)
DROP TABLE IF EXISTS student

所有的创建和删除最好都加上判断语句

3、MySQL数据管理

3.1、外键

方式一:在创建表的时候,增加约束(麻烦,比较复杂)
CREATE TABLE IF NOT EXISTS `student`( 
`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '学号',
`name` VARCHAR(20) NOT NULL DEFAULT '匿名' COMMENT '姓名', 
`pwd` VARCHAR(40) NOT NULL DEFAULT '123456' COMMENT'密码', 
`sex` VARCHAR(2) NOT NULL DEFAULT'女' COMMENT '性别', 
`birthday` DATETIME NOT NULL COMMENT '出生日期', 
`gradeid` INT(10) NOT NULL COMMENT'学生的年纪',
`address` VARCHAR(30) DEFAULT NULL COMMENT '家庭住址', 
`email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱', 
 PRIMARY KEY(`id`) ,
  KEY `FK_gradeid`(`gradeid`),
 CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade`(`gradeid`)
 )ENGINE=INNODB DEFAULT CHARSET=utf8; 

--学生表的gradeid列,要区引用年级表的gradeid
--定义外键key
--给这个外键增加约束(执行引用) reference 引用

CREATE TABLE `grade`(
`gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT'年级id',
`gradename` VARCHAR(40) NOT NULL  COMMENT'年级名称',
PRIMARY KEY (`gradeid`)
)ENGINE = INNODB DEFAULT CHARSET=utf8

删除有外键关系表的时候,必须要先删除引用别人的表(主动引用方,如上面的student-->引用 grade) 再删除被引用的表

方式二:
CREATE TABLE IF NOT EXISTS `student`( 
`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '学号',
`name` VARCHAR(20) NOT NULL DEFAULT '匿名' COMMENT '姓名', 
`pwd` VARCHAR(40) NOT NULL DEFAULT '123456' COMMENT'密码', 
`sex` VARCHAR(2) NOT NULL DEFAULT'女' COMMENT '性别', 
`birthday` DATETIME NOT NULL COMMENT '出生日期', 
`gradeid` INT(10) NOT NULL COMMENT'学生的年纪',
`address` VARCHAR(30) DEFAULT NULL COMMENT '家庭住址', 
`email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱', 
 PRIMARY KEY(`id`) 
  )ENGINE=INNODB DEFAULT CHARSET=utf8; 


CREATE TABLE `grade`(
`gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT'年级id',
`gradename` VARCHAR(40) NOT NULL  COMMENT'年级名称',
PRIMARY KEY (`gradeid`)
)ENGINE = INNODB DEFAULT CHARSET=utf8


--创建表的时候没有外键关系

ALTER TABLE `student` ADD CONSTRAINT `FK_gradeid` FOREIGN

--公式:ALTER TABLE 主表 ADD CONSTRAINT 约束名 FOREIGN KEY 作为外键的列) REFERENCES 从表 (列名)


以上的外键都是物理外键--->数据库级别的外键,不建议使用(避免数据库过多造成困扰)

  • 数据库就是单纯的表,只用来存数据,只有行(数据)和列(类名)

  • 通过外键可以使用多张表的数据,就是引用

3.2、DML语言

数据库意义:数据存储,数据管理

DML语言:数据操作语言

  • insert(插入)

  • update(添加)

  • delete(删除)

3.3、添加

--插入语句(添加)
--INSERT INTO 表名 (`列名1`,`列名2`,`列名3`) VALUES ('数据1'),('数据2'),('数据3')...
INSERT INTO `grade`(`gradename`) VALUES('大三')

--由于主键自增可以省略(如果不写列名,就会一一匹配)

--插入多个数据
INSERT INTO `grade`(`gradename`)
VALUES ('大二'),('大一')

INSERT INTO `student` (`name`) VALUES ('张三')


INSERT INTO `student` (`name`,`pwd`,`sex`) VALUES ('张三','aaa','男')

INSERT INTO `student`
 VALUES (3,'niubi','123a','男','2020-01-19',1,'西安','emall')

语法:INSERT INTO 表名 (列名1,列名2,列名3) VALUES ('数据1'),('数据2'),('数据3')...

注意事项:

  1. 列名和列名直接用英文逗号隔开

  2. 列名是可以省略的,但是后面的值必须要一一对应,不能缺少

  3. 可以同时插入多条数据,VALUES后面的值,需要使用英文逗号隔开

3.4、修改

update 修改对象(条件) set 原来的数据 = 新的数据

---修改学员的名字  带了条件 修改指定条件下的值
UPDATE `student`  SET `name` = '李四' WHERE id = 2


--不指定条件,会修改所有数据
UPDATE `student`  SET `name` = '长江七号' 

--修改多个属性,用逗号隔开列名

UPDATE `student`  SET `name` = 'lobort' ,`email` = '2445890216@qq.com' WHERE id =1

UPDATE `student`  SET `birthday` = CURRENT_TIME WHERE id = 2;


条件:where 语句

操作符 含义 事例 结果
= 等于 5 =6 false
<>或 != 不等于 5<>6 true
>
<
<=
>=
betweem...and... 再某个闭区间 betweem 3 and 5
and 并且 && 同真才真
or 或者 || 同假才假

语法:UPDATE 表名 SET 列名 = VALUES(新的数据) WHERE 条件

注意:

  • 列名最好带上``,不然可能会出现关键字
  • 筛选的条件,如果没有指定,则会修改所有的数据
  • value,可以是一个具体的值,也可以是一个变量(大多数指时间--->CURRENT_TIME)

3.5、删除

delete 命令

--删除所有数据
DELETE FROM student 

--删除指定数据
DELETE FROM student WHERE id = 3

TRUNCATE 命令

作用:完全清空数据库,表的结构和约束不会变

--清空grade表
TRUNCATE grade

delete 和 truncate 的区别

  • 相同点:都能删除数据,不会删除表的结构
  • 不同点
    • TRUNCATE 重新设置自增列---->计数器会归零
    • TRUNCATE 不会影响事务
--删除数据
DELETE FROM student WHERE id = 3

--情况grade表
TRUNCATE grade

--测试delete 和 truncate区别
CREATE TABLE `test`(
`id` INT(4) NOT NULL AUTO_INCREMENT,
`coll` VARCHAR(20) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE=INNODB DEFAULT CHARSET = utf8

INSERT INTO test(`coll`) VALUES (1),(2),(3)

DELETE FROM test  --不会影响自增

TRUNCATE test   --自增会归零

DELETE删除的问题,重启数据库:

  • innoDB:自增列胡重1开始(存在内存当中的,断电即失)
  • MyISAM:继续重上一个自增量开始(存在文件中的,不会丢

4、DQL查询数据

4.1、DQL

(Data Query Language:数据查询语言)

  • 所有的查询操作 Select
  • 简单的查询,复杂的查询都可以
  • 数据库中最核心的语言
  • 使用频率最高的语言

4.3、查询指定数据

--查询学生信息
SELECT * FROM student

--查询指定 列 的数据
SELECT `studentname`,`studentno` FROM `student`

--修改列的名字  AS:可以修改列名,也可以给查询结果命名
SELECT `studentname` AS 学号,`studentno` AS 学生姓名 FROM `student` AS 26班


--函数 CONCAT(a,b)
SELECT CONCAT('姓名:',`studentname`) AS 新名字 FROM student

语法:SELECT 列名 FROM 表

可以给查询的列名和表名修改名字,AS关键字

去重 distinct

作用:去除查询结果中重复的数据,只显示一条

--查询参加考试的同学
SELECT `studentno` FROM result

--去除重复数据
SELECT DISTINCT `studentno` FROM result

数据库的列

SELECT VERSION()  --查询数据库版本
SELECT 9*777+2 AS 计算结果   --计算数学表达式
SELECT @@auto_increment_increment   --查询自增变量步长

--所有学员考试成绩 + 1
SELECT `studentno`,`studentresult` + 1 AS '提分后' FROM result

数据库中的表达式:文本的值,列,null,函数,计算表达式,系统变量、、、

group by ---指定结果按照那几个字段来分组

having----过滤分组的记录必须满足的次要条件

4.3、where 条件语句

作用:检索数据中符合条件的值

搜索的条件由一个或多个表达式组成

逻辑运算符

运算符 语法 描述
and && a and b a && b 与:同真为真,一假就假
or || a or b a ||b 或:一真就真,同假才假
not ! not a !a 非:真假互换

模糊查询:比较运算符

运算符 语法 描述
is null a is null 如果操作符为null,结果为真
is not null a is not null 如果操作符不为null,结果为真
between a between b and c 若a在b和c之间,则结果为真
like a like b SQL 匹配,如果a匹配b,则结果为真
in (必须为精确值) a in (a1 , a2, a3...) 假设a是a1,a2、a3之中的一个,结果为真

其中 %代表0到任意个字符,__代表一个字符,仅配合like使用

--模糊查询(区间)
SELECT `studentno`,`studentresult` FROM result 
WHERE  studentno = 101

--查询姓张的同学
--like结合
SELECT `studentno`,`studentname` FROM `student`
WHERE studentname LIKE '张%'

--查询姓张的同学中,后面只有一个字的
SELECT `studentno`,`studentname` FROM `student`
WHERE studentname LIKE '赵_'

--查询名字之间有伟的
SELECT `studentno`,`studentname` FROM `student`
WHERE studentname LIKE '%伟%'


--=========IN=====

--查询1001,1002,1003号学员
SELECT `studentno`,`studentname` FROM `student`
WHERE studentno IN (1001,1002,1003)

4.3 select完整的语法:

select 去重(distinct) 要查询的列   from(注意:表和列 都可以另外取名)

as   xxx(别名)  join  要连接的表 on 等值判断

where(具体的值,子查询语句)

group by (通过那个列来分组)

having (过滤分组后的信息,条件和where一样的,只是位置不同)

order by  (通过那个字段排序)[升序/降序]

limit start index  pagesize 

4.4、联表查询

Join

操作 描述
Inner join 如果表中至少有一个匹配,就返回行
left join 即使右表中没有匹配,也会返回左表中所有的值
right join 即使左表中没有匹配,也会返回游标中所有的值

where 和 on 的区别

  • on和where都表示筛选条件,on先执行,where是在on筛选过后生成的临时表中继续筛选

自链接

父类

categoryid categoryName
2 信息技术
3 软件开发
5 美术设计

子类

pid categoryid categoryname
3 4 数据库
2 8 办公信息
3 6 web开发
5 7 ps技术
--查询父子信息
SELECT a.`categoryname` AS '父类',b.`categoryname` AS '子类' 
FROM `category` AS a,`category` AS b
WHERE a.`categoryid` = b.`pid`

4.5、分页和排序

排序

语法:ORDER BY 列名 ASC(升序) / DESC(降序)

分页

语法:LIMIT 从第几条数据显示 每页显示多少条数据

例子:LIMIT 5,10 -----> 从查出来的数据中第五条开始显示,每页显示10条数据

5、MySQL函数

5.1 数据库级别的MD5加密

什么是MD5?

主要增强算法复杂度和不可逆性

MD5不可逆,具体值的MD5是一样的

MD5破解网站的原理,背后有一个数据库有常用的数据加密后的值!

CREATE TABLE `testmd5`(
`id` INT(4) NOT NULL,
`name` VARCHAR(20) NOT NULL,
`pwd` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
)ENGINE =INNODB DEFAULT CHARSET= utf8

INSERT INTO testmd5 VALUES(1,'zhangsan','123456'),(2,'lisi','123456'),(3,'wangwu','123456')


DROP TABLE  `testmd5`

--加密
UPDATE testmd5 SET pwd = MD5(pwd) WHERE id =1

UPDATE testmd5 SET pwd = MD5(pwd) --加密全部

--插入的时候加密
INSERT INTO testmd5 VALUE(4,'xiaoming',MD5('123456'))

--如何校验:将用户传递进来的密码,进行md5加密,然后对比加密后的值
SELECT * FROM testmd5 WHERE `name` = 'xiaoming' AND pwd = MD5('123456')

6、事务transaction(ACID原则)

6.1、什么是事务

要么都成功,要么都失败

事务原则:ACID---原子性、一致性、隔离性、持久性

原子性

要么都成功,要么都失败(一个事务必须完全执行才算成功)

一致性

事务前后的数据完整性要保持一致

持久性

事务一旦提交则不可逆,被持久化到数据库中,不可以再修改这件事务

隔离性

事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,各个事务之间要相互隔离。

事务隔离产生的问题

  • 脏读:一个事务读取另一个未提交的数据。

  • 不可重复读:一个事务范围内两个相同的查询却返回了不同数据。

  • 幻读:一个事务范围内两个相同的查询却返回了不同数据。对应的是插入操作。

=======事务=====
--mysql事务是默认开启的
SET automommit = 0  --关闭自动提交
SET automommit = 1  --开启自动提交

--手动处理事务
SET autocommit = 0 -- 关闭自动提交

INSERT xx
INSERT  xx

--提交成功-->持久化
COMMIT
--提交失败-->回滚
ROLLBACK

--事务结束
SET autocommit = 1  ---开启自动提交

---扩展
SAVEPOINT  xx  --->设置一个临时保存点
ROLLBACK  TO  SAVEPOINT xx   --->回滚到xx临时保存点
RELEASE  SAVEPOINT xx  ---->撤销xx临时保存点

转账事务模拟

--转账
CREATE DATABASE shop CHARACTER SET utf8 COLLATE utf8_general_ci

USE shop
`account`
CREATE TABLE`account` (
`id` INT(3) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL,
`money` DECIMAL(9,2) NOT NULL,
PRIMARY KEY(`id`)
)ENGINE = INNODB DEFAULT CHARSET = utf8

INSERT INTO account(`name`,`money`)
VALUES ('A',2000.00),('B',10000.00)


-----模拟转账-----
SET autocommit = 0;  ---关闭自动提交
START TRANSACTION  ----开启一个事务

UPDATE account SET money = money-500 WHERE `name` = 'A'
UPDATE account SET money = money+500 WHERE `name` = 'B'

COMMIT;  ----提交
ROLLBACK ; ----回滚

SET autocommit = 1;

7、索引

索引(Index)是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:索引是数据结构

7.1、索引的分类

  • 主键索引

    • 唯一的标识,主键不可重复,智能又一个列作为主键
  • 唯一索引

    • 避免查询的列出现相同的数据,唯一索引可以重复,多个列都有可以标识为唯一索引
  • 常规索引

    • 默认的,index key 关键字来设置
  • 全文索引

    • 再特定的数据库引擎下才有,mylsam
    • 快速定位数据

7.2、 索引原则

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

索引的数据类型

hash类型的索引

Btree:innodb的默认数据结构

8、权限管理和备份

8.1、用户管理

--创建用户
CREATE USER `lobort` IDENTIFIED BY '123456'

--删除用户 
DROP USER lobort

--修改密码  当前
SET PASSWORD = PASSWORD('123456')

--修改指定用户的密码
SET PASSWORD FOR wdd = PASSWORD('123456')

--重命名
RENAME USER lobort1 TO wdd

--用户授权  --all privilegs 全部权限
GRANT ALL PRIVILEGES ON *.* TO wdd

--查询权限 
SHOW GRANTS FOR wdd  --GRANT ALL PRIVILEGES ON *.* TO 'wdd'@'%'  没有 授权 权限
SHOW GRANTS FOR root@localhost  --GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION


--撤销权限 REVOKE 哪些权限 在那个库撤销  给谁撤销
REVOKE ALL PRIVILEGES ON *.* FROM wdd

8.2、数据库备份

为什么要被封?

  • 保证重要数据不丢失
  • 进行数据转移

mysql数据库备份方式

  • 直接拷贝物理文件

  • 在sqlyog可视化工具中手动导出

    • 直接选中右键即可备份导出
  • 使用cmd命令行导出 mysqldump 命令

    #mysqldump -h 主机 -u 用户名 -p 密码  数据库  表名 >物理磁盘位置/文件名
    mysqldump -hlocalhost -uroot -p123456 school student >D:/a.sql
    
    #mysqldump -h 主机 -u 用户名 -p 密码  数据库  表名 >物理磁盘位置/文件名
    mysqldump -hlocalhost -uroot -p123456 school student grade >D:/a.sql
    
    #导入 
    #登录的情况下,切换到指定的数据库
    mysql -uroot -p123456
    #source 要导入的文件
    source d:/a.sql
    

9、规范数据库设计

9.1、为什么需要规范设计

当数据库比较复杂的时候,我们就需要设计

糟糕的数据库设计:

  • 数据冗余,浪费时间
  • 数据库插入和删除都会麻烦,还会导致异常【屏蔽物理外键的使用】
  • 程序的性能差

良好的数据库设计

  • 节省内存空间
  • 保证数据库的完整性
  • 方便开发系统

软件开发中,关于的数据库的设计

  • 分析需求:分析业务和需要处理数据的需求
  • 概要设计:分析各个数据之间的关系图 E-R图

设计数据库的步骤:(个人博客)

  • 收集信息,分析需求
    • 用户表(用户登录注销,用户的个人信息)
    • 分类表(文章分类,谁创建的)
    • 文章表(文章的具体内容)
    • 自定义表
    • 评论表
    • 友链表
    • 说说表
  • 标识实体
  • 标识实体之间的关系
    • 写博客:user--->blog
    • 创建分类:user--->category
    • 关注:user--->user
    • 友链:links
    • 评论:user--->user---->blog

9.2、三大范式

为什么需要数据规范化?

  • 信息重复
  • 更新异常
  • 插入异常
    • 无法正常显示信息
  • 删除异常
    • 丢失有效信息

三大范式

第一范式(1NF)

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

第二范式(2NF)

前提:必须满足第一范式

每张表只描述一个事情(后面的列必须和主键有关系且不能只与一部分主键有关)

第三范式(3NF)

前提:必须满足一二范式

第三范式需要确保数据表中的每一列都和主键直接相关,不能间接相关

规范性和性能的问题

关联查询的表不得超过三张表

  • 考虑商业化的需求和目标(成本,用户体验) 数据库的性能更加重要
  • 在规范型嫩固定问题的时候,需要适当的考虑规范性
  • 故意给某些表增加一些冗余的字段(从夺标查询中变为单表查询)
  • 故意增加一些计算列(从大数据量降低为小数据量的查询:索引)

10、JDBC(重点)

10.1、数据库驱动

驱动:

image-20221009135413722

程序会通过 数据库 驱动,和数据连接

10.2、JDBC

sun公司为了简化开发人的操作,提供了一个java操作数据库的规范 简称为JDBC

规范的实现由具体的厂商去做

对于开发人员,只需要掌握JDBC接口的操作

image-20221009135756861

10.3、第一个JDBC数据库

创建测试数据库

CREATE DATABASE `jdbcStudy` CHARACTER SET utf8 COLLATE utf8_general_ci;

USE `jdbcStudy`;

CREATE TABLE `users`(
 `id` INT PRIMARY KEY,
 `NAME` VARCHAR(40),
 `PASSWORD` VARCHAR(40),
 `email` VARCHAR(60),
 birthday DATE
);

 INSERT INTO `users`(`id`,`NAME`,`PASSWORD`,`email`,`birthday`)
VALUES(1,'zhangsan','123456','zs@sina.com','1980-12-04'),
(2,'lisi','123456','lisi@sina.com','1981-12-04'),
(3,'wangwu','123456','wangwu@sina.com','1979-12-04')

1、创建项目

2、导入数据库驱动

  • 项目新建lib文件夹,将数据库驱动复制过来,点击as a library

3、编写测试程序

public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // 1、加载驱动
        Class.forName("com.mysql.jdbc.Driver");//固定写法,加载驱动

        //2、用户信息和url
        String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
        String usename = "root";
        String password= "123456";

        //3、连接成功,数据库对象
        Connection connection = DriverManager.getConnection(url,usename,password);

        //4、执行sql对象
        Statement statement = connection.createStatement();

        //5、执行sql的对象去执行sql,可能存在结果,查看返回结果
        String sql = "SELECT * FROM `users`";

        ResultSet resultSet = statement.executeQuery(sql);

        while (resultSet.next()){
            System.out.println("id="+resultSet.getObject("id"));
            System.out.println("name="+resultSet.getObject("NAME"));
            System.out.println("pwd="+resultSet.getObject("PASSWORD"));
            System.out.println("email="+resultSet.getObject("email"));
            System.out.println("birth="+resultSet.getObject("birthday"));
            System.out.println("==========");
        }

        //6、释放连接 后用先释放
        resultSet.close();
        statement.close();
        connection.close();
    }

步骤总计:

1、加载驱动

2、连接数据库DriverManager

3、获得执行sql的对象 statemant

4、获得返回的结果集

5、释放连接

DriverManger

Class.forName("com.mysql.jdbc.Driver");//固定写法,加载驱动

//connevttion 代表数据
//数据库自动提交 connection.setautocommit
//事务提交   connection.commit();
//事务回滚  connection.rollback();

URL

String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";

//mysql默认端口号--3306
//jbdc:mysql://主机地址:端口号/数据库名?条件1&条件2&

10.4、statement对象

jbdc中的statement对象用于向数据库发送SQL语句,也可以这个对象完成对数据库的增删改查

statement对象的executeupdate方法,用于向数据库发送增、删、改的sql语句,execute update执行完以后,会返回一个整数

statement.executequery方法用于向数据库发送查询语句,executequery方法返回代表查询结果的resultset对象

CRUD操作-create

使用executeupdate(string sql)方法完成数据添加操作,示例操作:

 Statement statement = connection.createStatement();
        String sql = "insert into user(...) values(...)";
        int num = statement.executeUpdate(sql);
        if(num>0){
            System.out.println("插入成功");
        }

增删改的操作一样 使用executeupdate

CRUD-red

使用executeUpdate(String sql)方法完成数据查询操作,示例操作:

Statement statement = connection.createStatement();
        String sql = "select * from  user where id =1";
        ResultSet rs= statement.executeQuery(sql);
        if(rs.next()){
            System.out.println("");
        }


代码实现

1、提取工具类

package com.lobort.lesson02.utils;

import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JbdcUtils {
    private static String driver = null;
    private static String url = null;
    private static String usename = null;
    private static String password = null;


    static {

        try {
            InputStream in = JbdcUtils.class.getClassLoader().getResourceAsStream("resoursces/db.properties");
            Properties properties = new Properties();
            properties.load(in);

           driver = properties.getProperty("driver");
           url = properties.getProperty("url");
           usename = properties.getProperty("usename");
           password = properties.getProperty("password");

           //1、驱动只用加载一次
            Class.forName(driver);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取连接
    public static Connection getConnnection() throws SQLException {
        return DriverManager.getConnection(url,usename,password);
    }

    //释放连接
    public static void release(Connection conn, Statement st, ResultSet rs){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

2、编写增删改的方法 executeupdate

package com.lobort.lesson02;

import com.lobort.lesson02.utils.JbdcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestUpdate {
    public static void main(String[] args) {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JbdcUtils.getConnnection();
            st = conn.createStatement();
            String sql = "UPDATE users SET `NAME`='luo',`PASSWORD`='12334535',`email`='jahd83t7@qq.com'  WHERE id=1";
            int i = st.executeUpdate(sql);
            if(i>0){
                System.out.println("更新成功!");
            }

        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            JbdcUtils.release(conn,st,rs);
        }
    }
}

3、查询

package com.lobort.lesson02;

import com.lobort.lesson02.utils.JbdcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestSelect {
    public static void main(String[] args) {
        Connection conn = null;
        Statement st = null;
        ResultSet rs= null;

        try {
             conn = JbdcUtils.getConnnection();
             st = conn.createStatement();

             //sql语句
             String sql = "select * from users where id = 1 ";

            rs = st.executeQuery(sql);  //查询会返回一个结果集
            while(rs.next()){
                System.out.println(rs.getString("name"));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            JbdcUtils.release(conn,st,rs);
        }
    }
}

总结

  • 建立连接
  • 生成对象

SQL注入

package com.lobort.lesson02;

import com.lobort.lesson02.utils.JbdcUtils;

import java.sql.*;

public class SqlInsert {
    public static void main(String[] args) {
        login("' or' 1=1","' or '1=1");
    }


    //登录业务
    public static void login (String name,String password){
        Connection conn = null;
        Statement st = null;
        ResultSet rs= null;

        try {
            conn = JbdcUtils.getConnnection();
            st = conn.createStatement();

            //sql语句
            //SELECT * FROM users WHERE `NAME` = 'luo' AND `PASSWORD` = '123456'

            //String sql = "select * from users where `NAME` = '' or '1=1' and `password`= '"+password+"' ";
            String sql = "select * from users where `NAME` = '"+name+"' and `password`= '"+password+"' ";

            rs = st.executeQuery(sql);  //查询会返回一个结果集
            while(rs.next()){
                System.out.println(rs.getString("NAME"));
                System.out.println(rs.getString("password"));
                System.out.println("=======");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            JbdcUtils.release(conn,st,rs);
        }
    }
}

万能钥匙: ‘ or 1=1 ’

10.5 、PreparedStatement对象

防止sql注入,效率更高

增加

package com.lobort.lesson03;

import com.lobort.lesson02.utils.JbdcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TestInsert {
    public static void main(String[] args) {
        Connection coon = null;
        PreparedStatement st = null;


        try {
            coon = JbdcUtils.getConnnection();

            //区别:使用?占位  ?代替输入的数据
            String sql = "insert into users (id,`NAME`,`PASSWORD`,`email`,`birthday`) values (?,?,?,?,?)";
            st = coon.prepareStatement(sql);

            //手动赋值
            st.setInt(1,6);
            st.setString(2,"luo");
            st.setString(3,"123456");
            st.setString(4,"2445890216@qq.com");

            //注意:sql.date  数据库   java.sql.date()
            //   util.date   java    new date().gettime()  获得时间
            st.setDate(5,new java.sql.Date(System.currentTimeMillis()));


            //执行
            int i = st.executeUpdate();
            if(i>0){
                System.out.println("插入成功");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JbdcUtils.release(coon,st,null);
        }


    }
}

删除

package com.lobort.lesson03;

import com.lobort.lesson02.utils.JbdcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TestDelete {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;

        try {
            conn = JbdcUtils.getConnnection();

            //预编写sql语句
            String sql = "delete from users where id = ? or id = ?";
            st = conn.prepareStatement(sql);

            st.setInt(1,5);
            st.setInt(2,6);

            int i = st.executeUpdate();
            if(i>0){
                System.out.println("删除成功");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JbdcUtils.release(conn,null,null);
        }
    }
}


修改

package com.lobort.lesson03;

import com.lobort.lesson02.utils.JbdcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TestUpdate {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;

        try {
            conn = JbdcUtils.getConnnection();  //建立连接

            //预编译sql
            String sql = "update users set `NAME`= ? where id = ?;";
            st = conn.prepareStatement(sql);

            //参数赋值
            st.setString(1,"nichishi");
            st.setInt(2,2);

            int i = st.executeUpdate();
            if(i>0){
                System.out.println("成功了 ");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
         JbdcUtils.release(conn,st,null);
        }
    }
}

查询

package com.lobort.lesson03;

import com.lobort.lesson02.utils.JbdcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestSelect {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            conn = JbdcUtils.getConnnection();  //建立连接

            String sql = "select * from users where id = ?";
            st = conn.prepareStatement(sql);

            st.setInt(1,1);
            rs = st.executeQuery();
            while (rs.next()){
                System.out.println(rs.getString("NAME"));
            }


        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JbdcUtils.release(conn,st,rs);
        }


    }
}

防止sql注入

package com.lobort.lesson03;

import com.lobort.lesson02.utils.JbdcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class SqlZhuru {
    public static void main(String[] args) {
        login("luo","123456");
//        login("' or' 1=1","' or '1=1");
    }
    public static void login(String name, String password){


        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;


        try {
            conn = JbdcUtils.getConnnection();

            //sql预编译
            String sql = "select * from users where `NAME` = ? and `PASSWORD` = ?";
            st = conn.prepareStatement(sql);

            //传递参数
            st.setString(1,name);
            st.setString(2,password);

            rs = st.executeQuery();
            while (rs.next()){
                System.out.println(rs.getString("NAME"));
                System.out.println(rs.getString("password"));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JbdcUtils.release(conn,st,rs);
        }
    }
}

10.6、事务

1、建立连接 conn.setautocommit(false)

2、一组业务执行完毕,提交事务

3、可以在catch语句中显示的定义回滚,但是默认会自动回滚

package com.lobort.lesson04;

import com.lobort.lesson02.utils.JbdcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestTransation {
    public static void main(String[] args) {
        Connection conn =null;
        PreparedStatement  st =null;
        ResultSet rs =null;

        try {
            conn = JbdcUtils.getConnnection();  //建立连接

            //关闭自动提交
            conn.setAutoCommit(false);

            //业务1
            String sql1 = "update account set money = money-100 where name = 'A'";
            st = conn.prepareStatement(sql1);
            st.executeUpdate();

            //业务2
            String sql2 = "update account set money = money+100 where name = 'B'";
            st = conn.prepareStatement(sql2);
            st.executeUpdate();

            //业务完毕, 提交事务
            conn.commit();
            System.out.println("成功");


        } catch (SQLException e) {
            try {
                conn.rollback();  //如果失败就回滚
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            JbdcUtils.release(conn,st,rs);
        }
    }

}

posted @ 2022-10-11 19:45  lobort  阅读(30)  评论(0)    收藏  举报