Mysql学习记录

1.MySQL

JavaEE:企业级Java开发 Web

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

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

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

1.1 为什么学习数据库

市场需要

1.2 什么是数据库

数据库(DB)

概念:数据仓库,软件,安装在操作系统之上!SQL,可以存储大量的数据(500w之内)

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

1.3 数据库管理系统(DBMS )

1.4 安装教程

安装MySQL

安装SQLyog

1.5 连接数据库

mysql -uroot -password  #链接数据库
​
show databases;  #查看所有的数据库
​
mysql> use school   #切换数据库use数据库名
​
Database changed
​
show tables;    #查看数据库中的所有的表
​
describe student;   #显示数据库中所有的表的信息
​
create database student;   #创建一个数据库
​
exit;   --退出
​
#单行注释
/*多行注释*/
​
​

数据库xxx语言

DDL 定义

DML 操作

DQL 查询

DCL 控制

1.6Mac安装mysql

1.6.1第一步 官网下载:MySQL :: Download MySQL Community Server(打开直接是社区版的,基础阶段只需要社区版本,别的版本要付费)

2.操作数据库

2.1 操作数据库(了解) 数据库的增删改查

操作数据库>操作数据库中的表>操作数据库中的表的数据

  1. 创建数据库

    CREATE DATABASE [IF NOT EXISTS] (westos)#表名(
    `字段名` 列类型 [属性][索引][注释],
    `字段名` 列类型 [属性][索引][注释],
    `字段名` 列类型 [属性][索引][注释]
    ……
    `字段名` 列类型 [属性][索引][注释]
    )[表类型][字符集设置][注释]
  2. 删除数据库

    DROP DATABASE IF EXISTS westos;
  3. 使用数据库

    #tab键的上面,如果你的表名或者字段名是一个特殊字符,就要带`
    Eg:USE `school;`
  4. 查看数据库

    SHOW DATABASES #查看所有的数据库
  5. SHOW CREATE DATABASE school    #查看创建数据库的语句
    SHOW CREATE TABLE school     #查看Student数据表的定义语句
    DESC student   #显示表的结构
  6. 修改数据库

    #修改表名: ALTER TABLE 旧表名 RENAME AS 新表名
    ALTER TABLE teacher RENAME AS teacher1
    #增加表的字段: ALTER TABLE 表名 ADD 字段名 列属性
    ALTER TABLE teacherl ADD age INT(11)
    ​
    #修改表的字段 (重命名,修改约束!)
    #ALTER TABLE 表名 MODIFY 字段名 列属性[]
    ALTER TABLE teacherl MODIFY age VARCHAR(11) -- 修改约束
    #ALTER TABLE 表名CHANGE 旧名字 新名字 列属性[]
    ALTER TABLE teacher1 CHANGE age agel INT(1)-- 字段重名名
    ​
    #删除表的字段
    ALTER TABLE teacher1 DROP age1
    ​

2.2 数据类型

数值

  • tinyint 1个字节

  • smallint 2个字节

  • mediumint 3个字节

  • int 4个字节

  • bigint 8个字节

  • float 4个字节

  • double 8个字节

  • decimal 金融计算数

字符串

  • char 字符串固定大小的 0-255

  • varchar 可变字符串 0-65535 常用的String

  • tingtext 微型文本 2^8-1

  • text 文本串 2^16-1

时间日期

Java.util.Date

  • data

  • time

  • datetime YYYY-MM-DD HH:mm:ss

  • timestamp 时间戳 1970到现在的毫秒数

  • year 年份表示

null

  • 没有值,未知

  • 注意,不要使用NULL进行运算,结果为NULL

2.3 数据库的字段属性

Unsigned:

  • 无符号的整数

  • 声明了该列不能声明为负数

zerofill:

  • 0填充的

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

自增:auto incr

  • 通常用于id中

非空 NULL not null

  • null不填默认为空

默认

  • 默认初始值

规范拓展

/*每一个表,都必须存在以下五个字段!未来做项目用的,表示一个记录存在的意义
id 主键
`version`   乐观锁
is_delete   伪删除
gmt_create   创建时间
gmt_update   修改时间
*/

2.4 数据表的类型(面试)

#关于数据库引擎
/*
INNODB   默认使用~
MYISAM   早些年使用的
*/
MYISAMINNODB
事务支持不支持支持
数据行锁定不支持支持
外键约束不支持支持
全文索引支持不支持
表空间的大小较小较大,约为2倍

常规使用操作:

  • MYISAM 节约空间,速度较快

  • INNODB 安全性高,事务的处理,多表多用户操作

在物理空间存在的位置

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

本质还是文件的存储!

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

  • InnoDB在数据库中只有一个*.frm文件,以及上级目录下的ibdata1 文件

  • MYISAM对应文件

    • *.frm -表结构的定义文件

    • *.MYD 数据文件(data)

    • *.MYI 索引文件(Index)

设置数据库表的字符集编码

CHARSET=utf8

不设置的话,回事mysql默认的字符集编码 (不支持中文)

MySQL的默认编码是Latin,不支持中文

或者

在my.ini中配置默认的编码

character-set-server=utf8     #这种设置了全部sql文件,一般使用上面的方法,为每个数据库设置

3.MySQL数据管理

3.1 外键(了解)

  • 一般不用外键

  • 一个外键是另一个表的主键

3.2 DML语言(全部记住) 数据库中表的增删改查

数据库意义:数据库的存储与管理

DML语言:数据操作语言

  • 插入

insert into 表名(字段名1,字段名2) values('值1'),('值2')
  • 修改

    #不指定条件的情况下,会改动所有表
    update student set name ='嫦娥一号'
    #修改多个属性,逗号隔开
    update student set name ='嫦娥一号' where id =1
    #通过多个条件定位数据
    update student set name ='嫦娥一号' where id =1 and sex='女'
    操作符含义范围结果
    =
    <>或 !=不等于
    >
    <
    >=
    <=
    between ...and ...区间
    and
    or
  • 删除delete和truncate

delete

#删除数据
delete from 表名[where 条件]

#删除数据(这样全删)
delete from text
#删除数据(删除某一个)
delete from text where id =1

truncate

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

#清空 student 表
truncate student

delete和truncate的区别

  • turncate 重新设置自增量,数据归零

  • turncate 不会影响事务

4.DQL查询语言(重点)

4.1 DQL

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

  • 所有的查询操作,select

  • 数据库中最核心的语言,最重要的语句

  • 使用频率最高的语句

select完整字段

select[select 选项] 
	字段列表[字段别名] /* 
from 数据源
[where条件字句]       #指定结果需要满足的条件
[group by 字句]		 #指定结果按照哪几个字段来分组
[having 字句]			#过滤分组的记录必须满足的次要条件
[order by 字句]		#指定查询记录按一个或多个条件排序
[limit 字句]			#指定查询的记录从哪条至哪条

4.2 指定查询

#查询全部的学生   
select * from student
#查询指定字段
select `studentid`,`studentName` from student
#别名,给结果起一个名字   AS--起别名
select `studentid` AS 学号,`studentName` AS 学生姓名 from student
#函数  concat(a,b)
select concat('姓名:',studentName)  AS 新名字 from student
  • 去重

去重 distinct

select distinct `studentid`,`studentName` from student

4.3 where条件子句

逻辑运算符

运算符语法描述
and &&a and b 或a&&b
or ||
NOT !

模糊查询:比较运算符

运算符语法描述
is nulla is null如果操作符为NULL,结果为真
is not nulla is not null
betweena between b and c
likea like bSQL匹配,如果a匹配到b,则结果为真
ina in(a1,a2,a3)如a为 a1,a2,a3某一个,则结果为真
# 查询姓刘的同学
#like结合     %(代表0到任意个字符)    _(一个字符)
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============
select studentNo,studentName from student where StudentNo in(1001,1002,1003)

4.4 联表查询

join 对比

七种联表查询

  1. 交集

select s.studentNo,studentName,subjectNo,studentResult
from student AS s
inner join result AS r
on s.studentNo=r.studentNo
  1. 右+交集

select s.studentNo,studentName,subjectNo,studentResult
from student AS s
right join result AS r
on s.studentNo=r.studentNo     #on后面是连接条件
  1. 左+交集

select s.studentNo,studentName,subjectNo,studentResult
from student AS s
left join result AS r
on s.studentNo=r.studentNo
  1. 实例

/*查询参加考试的同学信息的  1.学号  2.学生姓名	3.科目名	4.分数
1.分析需求,分析查询的字段来自哪些表   student,result,subject
2.确定使用哪种连接查询   7种?
确定交叉点(交集)
判断的条件:学生表的中 studentNo =成绩表 studentNo
*/
select s.studentNo,studentName,subjectNo,studentResult
from student AS s
right join result AS r
on r.studentNo=s.studentNo
inner join subject sub
on r.subjectNo =sub.subjectNo


#查询学院所属的年级(学号,学生的姓名,年级名称)
select studentNo,studentName,GradeName
from student s
inner join grade g
on s.Gradeid=g.Gradeid

4.5 自连接(一表拆二表)

自连接(用于属性结构的 双亲表示法 且只有两层层次才可以用)

自己连接自己:也就是自己一张表当两张表使用

比如数据库关系如下表

catagoryidpidcatagoryName
31软件开发
51美术设计
43数据库
82办公信息
21信息技术
63Web开发
75Ps技术

父类

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

子类

pidcatagoryidcatagoryName
34数据库
28办公信息
36Web开发
57美术设计

操作:查询父类对应的子类关系

父类子类
信息技术办公信息
软件开发数据库
软件开发Web开发
美术设计Ps技术
#查询父子信息
select categoryName as '父栏目',categoryName as '子栏目'
from catagory as a,catagory as b
where a.categoryid =b.pid

4.6 分页limit和排序order by

select s.studentNo,studentName,subjectName,studentResult
from student as s
inner join result r
on s,studentNo = r.studentNo
inner join subject as sub
on s,subjectNo = sub.subjectNo
where subjectName ='数据库结构'
order by desc   --desc降序排列    asc--升序排列
limit 0,5     -- 从哪里开始,一页有几个

4.7 子查询

where() 视频P23 不太明白

本质:在where语句中嵌套一个子查询语句

where(select * from)

联表查询写法

#查询课程为  高等数学-2  且分数不小于80的同学的学号和姓名
select s.studentNo,studentName
from student s
inner join result r
on s.studentNo=r.studentNo
inner join subject sub
on r.subjectNo=sub.subjectNo
where subjectName ='高等数学-2' and studentResult>=80

子查询写法

#分数小于80分的学生的学号和姓名
select distinct s.studentNo,studentName
from student s
inner join result r
on r.studentNo=s.studentNo
where studentResult>=80

#改造,在这个基础上再增加一个高等数学-2
select distinct s.studentNo,studentName
from student s
inner join result r
on r.studentNo=s.studentNo
where studentResult>=80 and subjectNo=(     为子查询写法
	select subjectNo from subject
    where subjectName='高等数学-2' 
)

#在改造
select  studentNo,studentName from student where studentNo in(
	select studentNo from result where studentResult>80 and subjectNo=(
        select subjectNo from subject where subjectName ='高等数学-2'
    )
)

4.7 分组和过滤

#查询不同课程的平均分,最高分,最低分,平均分大于80
#核心  :(根据不同的课程分组)
select subjectName,avg(studentResult) as 平均分,max(studentResult) as 最高分,min(studentResult) as 最低分
from result r
inner join subject sub
on r.subjectNo=sub.subjectNo
group by r.subjectNo      #通过什么字段来分组
having 平均分>80         #group后面不用where用having

5.MySQL函数

官网查询使用

5.1 常用函数

百度可查常用函数

5.2 聚合函数

#=============聚合函数=============
#都能够统计表中的数据(想查询一个和表中有多少个记录,就用这个count())
select count('studentName') from student  #count(字段) 会忽略所有的null值
select count(*) from student      #count(*),不会忽略null值,本质计算行数
select count(1) from student		#count(1),不会忽略null值,本质计算行数

select sum(studentResult) as 总和 from result       #总和
select avg(studentResult) as 平均分 from result		#平均分
select max(studentResult) as 最大值 from result		#最大值
select min(studentResult) as 最小值 from result		#最小值

5.3 数据库级别的MD5加密

什么是MD5

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

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=utf-8

#明文密码
insert into testmd5 values(1,'zhangsan','123456'),(2,'lisi','123456'),(3,'wangwu','123456')

#加密id=1的密码
update testmd5 set pwd=MD5(pwd) where id=1

#加密所有的密码
update testmd5 set pwd=MD5(pwd) 

#插入时加密
insert into testmd5 values(1,'zhangsan',MD5'123456'),(2,'lisi',MD5'123456'),(3,'wangwu',MD5'123456')

#如何校验    将用户传递进来的密码,进行MD5加密,然后对比加密后的值
select * from testmd5 where 'name'='xiaoming' and pwd =MD5('123456')

6.事务

6.1 什么是事务

数据库中:事务(Transaction)是访问和更新数据库的程序执行单元,事务中可能包含一个或多个sql语句,这些语句要么都执行,要么都不执行。

简单理解:将多各操作打包在一起执行,且支持回滚,就是事务!(事务)[事务的【ACID】四大原则 - 知乎 (zhihu.com)]

事务原则:ACID 原则

  • 原子性

  • 最终一致性

    • 交易的双方最终(价格总数)要保证不变

  • 持久性

    • 事务没有提交,恢复到原装

    • 事务已经调教,持久化到数据库

  • 隔离性

    • 事务隔离级别

1.脏读

指一个事务读取了另外一个事务未提交的数据。(读后写)

2.不可重复读

3.幻读(写后读)

执行事务 mysql是默认开启事务自动提交的

#模拟转账:事务
set autocommint=0;   #关闭自动提交事务
start transaction  #开启一个事务
update account set money=money-500 where 'name'='A'    #A公司减500快
update account set money=money+500 where 'name'='B'    #B公司加500快

commit;      #提交事务,就被持久化
rollback;		#事务回滚

set autocommit=1;		事务恢复默认值	

一般事务的提交事务commit放在try中,回滚rollback放在catch中

7.索引

MySQL官方对索引的定义为:索引(index)是帮助MySQL高效获得数据的数据结构

提取句子主干,就可以得到索引的本质:索引是数据结构。

7.1 索引的分类

在一个表中,主键索引只能有一个,唯一索引可以有多个

  • 主键索引(primary key)

    • 唯一的标识,主键不可重复,只能有一个列作为主键

  • 唯一索引(union key)

    • 避免重复的列出现,唯一索引可以重复,可以多个列有唯一索引

  • 常规索引(key/index)

    • 默认的

  • 全文索引(FullText)

    • 在特定的数据库引擎下才有

7.2测试索引

7.3索引原则

  • 索引不是越多越好

  • 不要对进程变动数据加索引

  • 小数据量的表不需要加索引

  • 索引一般夹在常用来查询的字段上

索引的数据结构

Hash类型的索引

Btree:innodb的默认数据结构

8.权限管理和备份

8.1 用户管理

本质:就是群主对群的管理

只有linex中使用window下可视化的

8.2 备份

为什么要备份:

  • 保证数据不丢失

  • 数据转移

MySQL备份数据库方式

  • 直接拷贝物理文件

  • 可视化工具中右键备份与导出

  • 使用命令行 mysqldump导出

    • #导出
      mysqldump -hlocalhost -uroot -p123456 school student >D:a.sql
      
      #导入
      mysql -u用户名 -p密码 库名<备份文件地址

9.数据库规范设计

9.1 为什么需要设计

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

糟糕的数据库设计

  • 数据冗余,浪费空间

  • 数据库插入和删除都会麻烦,异常【一般不使用物理外键】

  • 程序的性能差

良好的数据库设计

  • 节省内存空间

  • 保证数据库的完整性

  • 方便开发

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

  • 分析需求:分析业务和需要处理的数据库的需求

  • 概要设计:设计关系图 E-R图

9.2 三大范式

为什么需要数据规范化

  • 信息重复

  • 更新异常

  • 插入异常

    • 无法正常显示信息

  • 删除异常

    • 丢失有效的信息

三大范式[关系型数据库设计:三大范式的通俗理解 - 景寓6号 - 博客园 (cnblogs.com)]

第一范式(1NF)

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

第二范式(2NF)

前提:满足第一范式

第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函数依赖)

第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言),通俗来讲是每张表只描述一件事情。

第三范式(3NF)

前提:满足第二范式

规范性 和 性能的问题

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

  • 考虑商业化的需求和目标,(成本,用户体验!)数据库的性能更加重要

  • 在规范性能的问题的时候,需要适当考虑一下规范性

  • 故意给某些表增加一些冗余字段(从多表查询变为单表查询)

  • 故意增加一些计算列(从大数据量降低为小数据量的查询:索引)

10JDBC

10.1 数据库驱动

程序需要调入包(驱动)来进行执行

10.2 JDBC

Java 操作数据库的统一规范

对于开发人员只需要了解JDBC接口即可(相当于那个文件挂载的意思)

除了java.sql和javax.sql还需要导入一个数据库驱动包mysql-connector-java(Mearn)或者在MySQL官网下载

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.导入依赖包

3.编写测试代码

package com.hang.study01;
import java.sql.*;

//我的第一个JDBC程序
public class JDBCFrist {

    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";  //useUnicode=true&characterEncoding=utf8&useSSL=true"固定的
        String username="root";
        String password="123456";

        //3.连接成功,数据库对象
        Connection connection= DriverManager.getConnection(url,username,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"));
        }
        //6.释放连接
        resultSet.close();
        connection.close();
        statement.close();
    }
}

步骤总结

  1. 加载驱动

  2. 连接数据库DriverManager

  3. 获得执行SQL的对象statement

  4. 获得返回的结果集

  5. 释放连接

DriverManager

Class.forName("com.mysql.jdbc.Driver");   //会报错先把异常抛出   ,固定写法,加载驱动
Connection connection= DriverManager.getConnection(url,username,password);

//connection   代表数据库对象,数据库语言都可以在这里应用
connection.getAutoCommit();         //数据库设置自动提交
connection.commit();        //事务提交
connection.rollback();        //事务回滚

URL

String url ="jdbc:mysql://localhost:3306/jdbcstudy?
//协议:服务器(主机地址:端口号) :数据库名?参数1&参数2&.....
    
    
//Oracle中的URL与MySQL中不同
 
//1521--为Oracle端口号    
//jdbc:oracle:thin:@localhost:1521:sid

Statement执行SQL对象 PrepareStatement执行SQL的对象

String sql="select * from users"
    
statement.executeQuery(sql);       //查询操作返回ResultSet
statement.execute(sql);           //可用于所有操作就是效率问题
statement.executeUpdate(sql);    //可用于增删改查

resultSet查询结果集,封装了所有的查询结果

获取指定的数据类型

resultSet.getObject            //什么类型都可以获取   ,肯定浪费时间
resultSet.getInt				//获取整数类型
resultSet.getString
resultSet.getFloat 
resultSet.getDate  

遍历数据

resultSet.beforeFirst()        //第一个
resultSet.afterLast()			//最后一个
resultSet.next()				//下一个
resultSet.provious()			//前一个
resultSet.absolute(row)			//移动到指定行

释放资源

//6.释放连接
resultSet.close();
connection.close();
statement.close();

10.4 statement对象

Idbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改査,只需要通过这个对象向数据库发送增删改查语句即可。 Statement对象的executeUpdate方法,用于向数据库发送(增、删、改)sql语句,executeUpdate执行完后,将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)。 Statement.executeQuery方法用于向数据库发送査询语句,executeQuery方法返回代表査询结果的Resultset对象。

CRUD 操作-create

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

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

CRUD 操作-update

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

 Statement statement=connection.createStatement();
 String sql="update users set name ='' where name =''";
int sum =statement.excuteUpdate(sql);
if(num>0)
{
    System.out.println("修改名字成功");
}

CRUD 操作-Query

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

 Statement statement=connection.createStatement();
 String sql="select * from users where id =1";
ResultSet resultSet=statement.executeQuery(sql);
 while(resultSet.next()){
     System.out.println();         //根据需要映射到前端
 }

statement步骤

  1. 提取工具类

  1. 读取工具类

读取工具类的具体函数

package com.hang.study02.utils;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JdbcUtils {
        private static String driver;
        private static String url;
        private static String username;
        private static String passsword;

        static {
            try{

                InputStream in=JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");

                //拿到输入流
                Properties properties = new Properties;
                properties.load(in);
                //此时输入流在in对象中


                //此时拿到db.properties中各个的值
                driver= properties.getProperty("driver");
                url= properties.getProperty("url");
                username= properties.getProperty("username");
                passsword= properties.getProperty("passsword");

                //1.驱动只加载一次
                Class.forName(driver);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

        }
        //2.获取连接
    public static Connection getConnection() throws SQLException {
            return DriverManager.getConnection(url,username,passsword);
    }
        //3.释放连接
    public static void release(Connection connection, Statement statement , ResultSet resultSet){
    if (resultSet!=null){
        try {
            connection.close();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    if (statement!=null){
        try {
            connection.close();
        } catch (SQLException e) {
                throw new RuntimeException(e);
        }
    }
    if (connection!=null){
        try {
            connection.close();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    }
}

 public static void main(String[] args) {
        Connection connection = null;
        Statement statement=null;
        ResultSet resultSet=null;       //这个一般只有在查询语句中使用

        try {
            connection= JdbcUtils.getConnection();        //这个是utils包中定义的那个拿到connection的函数体
            statement=connection.createStatement();     //获取SQL的执行对象
            String sql="insert into users(id,`NAME`,`PASSWORD`,`email`,`birthday`) values('4','hang','123456','1@qq.com','2001-01-20')";
            int i= statement.executeUpdate(sql);
           if(i>0){
               System.out.println("插入成功");
           }
        } catch (SQLException e) {
           e.printStackTrace();
        }finally {
            JdbcUtils.release(connection,statement,resultSet);
        }
    }

 public static void main(String[] args) {
        Connection connection = null;
        Statement statement=null;
        ResultSet resultSet=null;       //这个一般只有在查询语句中使用
        try {
            connection= JdbcUtils.getConnection();        //这个是utils包中定义的那个拿到connection的函数体
            statement=connection.createStatement();     //获取SQL的执行对象
            String sql="delete from users where id= 4";
            int i= statement.executeUpdate(sql);
            if(i>0){
                System.out.println("删除成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(connection,statement,resultSet);
        }
    }

  public static void main(String[] args) {
        Connection connection = null;
        Statement statement=null;
        ResultSet resultSet=null;       //这个一般只有在查询语句中使用

        try {
            connection= JdbcUtils.getConnection();        //这个是utils包中定义的那个拿到connection的函数体
            statement=connection.createStatement();     //获取SQL的执行对象
            String sql="update users set `name`='hang',`email`='702669001@qq.com' where id =1";
            int i= statement.executeUpdate(sql);
            if(i>0){
                System.out.println("更新数据成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(connection,statement,resultSet);
        }
    }

 public static void main(String[] args) {
        Connection connection = null;
        Statement statement=null;
        ResultSet resultSet=null;       //这个一般只有在查询语句中使用
        try {
            connection= JdbcUtils.getConnection();        //这个是utils包中定义的那个拿到connection的函数体
            statement=connection.createStatement();     //获取SQL的执行对象
            String sql="select * from users";
            resultSet= statement.executeQuery(sql);
            if(resultSet.next()){
                System.out.println("id:"+resultSet.getInt("id"));
                System.out.println("name:"+resultSet.getString("name"));
                System.out.println("password:"+resultSet.getString("password"));
                System.out.println("email:"+resultSet.getString("email"));
                System.out.println("birthday:"+resultSet.getDate("birthday"));
                System.out.println("查询成功\n================================\n");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(connection,statement,resultSet);
        }
    }

10.5 SQL注入

漏洞

10.6 PreparedStatement对象

PreparedStatement与statement的本质区别就是可以防止SQL注入

增加

public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement=null;
        ResultSet resultSet=null;       //这个一般只有在查询语句中使用
        try {
            connection= JdbcUtils.getConnection();        //这个是utils包中定义的那个拿到connection的函数体
            //区别
            //使用? 占位符代替参数
            String sql = "INSERT  INTO users (id, `NAME`, `PASSWORD`, email, birthday) VALUES (?,?,?,?,?)";
            preparedStatement=connection.prepareStatement(sql);    //预编译SQL,险些SQL,然后不执行

            //手动给参数赋值
            preparedStatement.setInt(1,4);
            preparedStatement.setString(2,"lu");
            preparedStatement.setString(3,"123456");
            preparedStatement.setString(4,"70266239001@qq.com");
            //st.setDate(5, date);
            preparedStatement.setDate(5,new Date(System.currentTimeMillis()));

            int i=preparedStatement.executeUpdate();
            if(i>0){
                System.out.println("插入成功");
            }
        } catch (SQLException e) {
           e.printStackTrace();
        }finally {
            JdbcUtils.release(connection,preparedStatement,resultSet);
        }
    }

删除

 public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement=null;
        ResultSet resultSet=null;       //这个一般只有在查询语句中使用
        try {
            connection= JdbcUtils.getConnection();        //这个是utils包中定义的那个拿到connection的函数体
            //区别
            //使用? 占位符代替参数
            String sql = "delete from users where id= ?";
            preparedStatement=connection.prepareStatement(sql);    //预编译SQL,险些SQL,然后不执行

            //手动给参数赋值
            preparedStatement.setInt(1,4);
            //st.setDate(5, date);

            int i=preparedStatement.executeUpdate();
            if(i>0){
                System.out.println("删除成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(connection,preparedStatement,resultSet);
        }
    }

更新

public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement=null;
        ResultSet resultSet=null;       //这个一般只有在查询语句中使用
        try {
            connection= JdbcUtils.getConnection();        //这个是utils包中定义的那个拿到connection的函数体
            //区别
            //使用? 占位符代替参数
            //update users set `name`='hang',`email`='702669001@qq.com' where id =1
            String sql = "update users set `name`='yi' where id=?";
            preparedStatement=connection.prepareStatement(sql);    //预编译SQL,险些SQL,然后不执行
            //手动给参数赋值
            preparedStatement.setInt(1,1);

            int i=preparedStatement.executeUpdate();
            if(i>0){
                System.out.println("更新成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(connection,preparedStatement,resultSet);
        }
    }

查询

public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement=null;
        ResultSet resultSet=null;       //这个一般只有在查询语句中使用
        try {
            connection= JdbcUtils.getConnection();        //这个是utils包中定义的那个拿到connection的函数体
            String sql="select * from users where id =?";
            preparedStatement=connection.prepareStatement(sql);
            preparedStatement.setInt(1,1);
            resultSet= preparedStatement.executeQuery();
            if(resultSet.next()){
                System.out.println("id:"+resultSet.getInt("id"));
                System.out.println("name:"+resultSet.getString("name"));
                System.out.println("password:"+resultSet.getString("password"));
                System.out.println("email:"+resultSet.getString("email"));
                System.out.println("birthday:"+resultSet.getDate("birthday"));
                System.out.println("查询成功\n================================\n");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.release(connection,preparedStatement,resultSet);
        }
    }

10.7 事务

要么都成功,要么都失败

模拟转账

数据库代码

CREATE TABLE account(
    id Int PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(40),
    money FLOAT
);

/*插入测试数据*/
insert into account(name,money) values('A',1000);
insert into account(name,money) values('B',1000);
insert into account(name,money) values('B',1000);

java代码

public static void main(String[] args) {
        Connection connection=null;
        PreparedStatement preparedStatement=null;
        ResultSet resultSet=null;
        try {
            connection= JdbcUtils.getConnection();   //这个是utils包中定义的那个拿到connection的函数体

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

            String sql1="update account set money=money-100 where name = 'A'";
            preparedStatement=connection.prepareStatement(sql1);
            preparedStatement.executeUpdate();

            String sql2="update account set money=money+100 where name = 'B'";
            preparedStatement=connection.prepareStatement(sql2);
            preparedStatement.executeUpdate();

            //业务完毕,提交事务
            connection.commit();
            System.out.println("转账成功");
        } catch (SQLException e) {
            try {
                connection.rollback();
            } catch (SQLException ex) {
                e.printStackTrace();
            }
           e.printStackTrace();
        }
        finally {
            JdbcUtils.release(connection,preparedStatement,resultSet);
        }
    }

10.8 数据库连接池

数据库连接--执行完毕--释放 --每次连接浪费很大空间

池化技术:准备一些预先的资源,过来就连接预先准备好的

最小连接数:10

最大连接数:15

等待超时:100ms

编写连接池,实现一个接口 DateSourse

开源数据源实现

DBCP

C3P0

Druid:阿里巴巴

DBCP

需要用到的jar包DBCP数据源jar包下载与IDEA配置以及NoClassDefFoundError问题解决_dbcpjar包下载-CSDN博客

连接配置 properties格式

#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=123456

#<!-- 初始化连接 -->
initialSize=10

#最大连接数量
maxActive=50

#<!-- 最大空闲连接 -->
maxIdle=20

#<!-- 最小空闲连接 -->
minIdle=5

#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:【属性名=property;】
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=UTF8

#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true

#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=

#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值