MySQL

初识MySQL

什么是数据库?为什么要学数据库?

为什么学习数据库

  1. 岗位需求
  2. 大数据时代~
  3. 被迫需求:存数据
  4. 数据库是所有软件体系中最核心的存在 DBA

什么是数据库

  • 数据库(DB,DataBase)

  • 概念:数据仓库,软件,安装在操作系统上(Windonw、Linux、Mac)之上! SQL

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

关系型数据库和非关系型数据库区别

关系型数据库:(SQL)

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

非关系型数据库:(NoSQL)Not Only

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

DBMS(数据库管理系统)

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

MySQL简介

MySQL是一个关系型数据库管理系统

MySQL是最好的RDBMS(关系型数据库)应用软件之一

开源的数据库软件

体积小,速度快,总体拥有成本低,招人成本低,所有人必须会~

中小型网站,或者大型网站,集群!

连接数据库

命令行连接!

mysql -uroot -proot  --连接数据库
--  所有的语句都使用;结尾
show databases;  --查看所有的数据库

mysql> use school --切换数据库 use 数据库名
Database changed

show tables;  --查看数据库中所有的表
desc student; --显示数据库中所有表的信息

create database westos; --创建一个数据库

数据库xxx语言

DDL 定义

DML 操作

DQL 查询

DCL 控制

操作数据库( 了解 )

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

mysql 不区分大小写

操作数据库

  1. 创建数据库
create database westos;
  1. 删除数据库
drop database westos;
  1. 使用数据库
use `school`
  1. 查看数据库
show databases;  --查看所有的数据库

数据库的列类型

数值

  • tinyint 十分小的数据 1个字节
  • smallint 较小的数据 2个字节
  • int 标准的整数 4个字节
  • bigint 较大的数据 8个字节
  • float 浮点数 4个字节
  • double 浮点数 8个字节 ( 精度问题 ! )
  • decimal 字符串形式的浮点数 一般金融计算的时候使用

字符串

  • char 字符串 0~255
  • varchar 可变字符串 0~65535 常用的变量
  • tinytext 微型文本 2^8 -1
  • text 文本串 2^16 -1 保存大文本

时间日期

java.util.Date

  • date YYYY-MM-DD 日期格式
  • time HH:mm:ss 时间格式
  • datetime YYYY-MM-DD HH:mm:ss 最常用的时间格式
  • timestamp 时间戳, 1970.1.1 到现在的毫秒数 ! 也较为常用
  • year 年份表示

null

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

数据库的字段属性 ( 重点 )

无符号:

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

零填充:

  • 不足的位数,使用0来填充 int ( 3 ) 5 --- 005

自动递增

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

非空 NULL not null

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

默认

  • 设置默认的值
  • sex , 默认值为男, 如果不指定该列的值 则会有默认的值 !

创建数据库表 ( 重点 )

-- 目标 : 创建一个school数据库
-- 创建学生表(列,字段) 使用SQL 创建
-- 学号int 登录密码varchar(20) 姓名性别varchar(2),出生日期,家庭住址

-- 注意点,使用英文()  表的 名称 和 字段 尽量用 ` ` 括起来
-- AUTO_INCREMENT 自增
-- 字符串使用 单引号括起来!
-- 所有语句后面加 , 最后一个不用加
-- PRIMARY KEY 主键,一般一个表只有一个唯一的主键
CREATE TABLE `student` (
  `id` int(4) NOT NULL AUTO_INCREMENT COMMENT '学号',
  `name` varchar(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
  `pwd` varchar(20) NOT NULL DEFAULT '123456' COMMENT '密码',
  `sex` varchar(2) NOT NULL DEFAULT '女' COMMENT '性别',
  `birthday` datetime DEFAULT NULL COMMENT '出生日期',
  `address` varchar(100) DEFAULT NULL COMMENT '家庭住址',
  `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

格式

CREATE TABLE [IF NOT EXISTS] `表名`(
    '字段名' 列类型 [属性] [索引] [注释],
    '字段名' 列类型 [属性] [索引] [注释],
    ......
    '字段名' 列类型 [属性] [索引] [注释],
    )

修改删除表

修改

-- ALTER TABLE 旧表名 RENAME AS 新表名
ALTER TABLE student RENAME AS student1

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

-- 修改表的字段(重命名,修改约束!)
-- ALTER TABLE 表名 MODIFY 字段名 列属性[]
ALTER TABLE student1 MODIFY id VARCHAR(11)  -- 修改约束
-- ALTER TABLE 表名 CHANGE 旧名字 新名字 列属性[]
ALTER TABLE student1 CHANGE id  id1 INT(11) -- 字段重命名

-- 删除表的字段: ALTER TABLE 表名 DROP 字段名
ALTER TABLE student1 DROP id1

删除

-- 删除表(如果表存在再删除)
DROP TABLE IF EXISTS studen1

所有的创建和删除操作尽量加上判断

注意点:

  • `` 字段名,用这个包裹
  • 注释: -- /**/
  • sql 关键字大小写不敏感,建议写小写
  • 所有的符号用英文

MySQL数据管理

外键(了解即可)

DML语言(全部记住)

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

DML语言: 数据操作语言

添加( Insert )

-- 插入语句(添加)
-- insert into 表名([字段名1,字段2,字段3]values('值1'),('值2'),(值3,....)
INSERT INTO `grade` (`gradeid`) VALUES('1')

-- 一般写插入语句,我们一定要数据和字段一一对应!

-- 插入多个字段
INSERT INTO `grade` (`gradeid`,`gradename`) VALUES('2','张三')

INSERT INTO `grade` (`gradeid`,`gradename`) 
VALUES('3','李四'),('4','王五')

语法:insert into 表名([字段名1,字段2,字段3]values('值1'),('值2'),(值3,....)

注意事项:

  1. 字段和字段之间使用英文逗号隔开
  2. 字段是可以省略的,但是后面的值必须要一一对应,不能少
  3. 可以同时插入多条数据,VALUES后面的值,需要用,隔开即可

修改( update )

-- 修改学员名字,带了条件
UPDATE `student` SET `name`='狂神' WHERE id=1;

-- 不指定条件的情况下,会改动所有表! (小心删库跑路)
UPDATE `student` SET `name`='长江七号'

-- 修改多个属性
UPDATE `student` SET `name`='南子旭',`email`='766656302@qq.com' WHERE id=1;

-- 语法:
-- 修改多个属性
-- UPDATE 表名 SET colnum_name = value,[colnum_name = value,....] WHERE [条件];

条件: where 子句 运算符 id等于某个值

操作符返回布尔值

操作符 含义 范围 结果
= 等于 5=6 false
<> 或 != 不等于 5<>6 true
>
<
>=
<=
BETWEEN ... AND ... 在某个范围内 [2,5]
AND 和 && 5>1 and 1>2 false
OR 或 || 5>1 or 1>2 true
-- 通过多个条件定位数据
UPDATE `student` SET `name`='迪迦' WHERE `name`='南子旭' AND `sex`='男'

语法:UPDATE 表名 SET colnum_name = value,[colnum_name = value,....] WHERE [条件];

注意:

  • colnum_name 是数据库的列,尽量带上 ``
  • 条件,筛选的条件,如果没有指定,则会修改所有的列
  • value,是一个具体的值,也可以是一个变量
-- 设置时间为当前时间
UPDATE `student` SET `birthday`=CURRENT_TIME WHERE `name`='南子旭' AND `sex`='男'

删除( delete )

语法:DELETE FROM 表名 [WHERE 条件];

-- 删除数据(避免这样写,会全部删除)
DELETE FROM `student`

-- 删除指定数据
DELETE FROM `student` WHERE id=4;

TRUNCATE 命令

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

-- 清空 student 表
TRUNCATE  `student`

delete 和 TRUNCATE 区别

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

DQL查询数据( 最重点 )★

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

  • 所有的查询操作都用它 Select
  • 简单的查询,复杂的查询它都能做~
  • 数据库中最核心的语言,最重要的语句
  • 使用频率最高的语句

SELECT完整语法

SELECT [ALL | DISTINCT]
{* | TABLE.* |[TABLE.field1[AS alias1][,TABLE.field2[AS alias2]][,...]]}
FROM TABLE_name [as TABLE_alias]
	[LEFT | RIGHT | INNER JOIN TABLE_name2] -- 联合查询
	[WHERE ...] -- 指定结果需满足条件
	[GROUP BY ...] -- 指定结果按照哪几个字段来分组
	[HAVING] -- 过滤分组的记录必须满足的必要条件
	[ORDER BY] -- 指定查询记录按照一个或多个条件排序
	[LIMIT {[OFFSET,]ROW_COUNT | ROW_COUNTOFFSET OFFSET}];
	-- 指定查询的记录从哪条至哪条
	注意:[]代表可选的,{}代表必选

指定查询字段

-- 查询全部学生的信息  SELECT 字段 FROM 表
SELECT * FROM student

-- 查询指定字段
SELECT `id`,`name` FROM student

-- 别名:给结果起一个名字 AS
SELECT `id` AS 学号,`name` AS 姓名 FROM student

-- 函数Concat (a,b)
SELECT CONCAT('姓名',name) AS 新名字 FROM student

字段:SELECT 字段... FROM 表

有时候,列名字不是那么的见名知意. 我们起别名 AS 字段名 AS 别名 表名 AS 别名

去重 distinct

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

SELECT DISTINCT `name` FROM `student` -- 发现重复数据,去重

数据库的列 ( 表达式 )

-- 考试成绩加一分查看
SELECT `id`,`score`+1 AS '加分后' FROM student

SELECT 100*3-1 AS '计算结果' -- 用来计算

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

SELECT 表达式 FROM 表

where 条件子句

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

搜索的条件由一个或多个表达式组成! 结果 布尔值

逻辑运算符

运算符 语法 描述
and && a and b a && b 逻辑与,两个都为真,结果为真
or || a or b a || b 逻辑或,其中一个为真,结果为真
Not ! not a ! a 逻辑非,真假假真!

尽量使用英文字母

-- 查询分数在 95-150 之间
SELECT id ,`score` FROM student
WHERE score>=95 AND score<=150 

-- 模糊查询(区间)
SELECT id ,`score` FROM student
WHERE score BETWEEN 95 AND 150 

-- 查询除了1号之外的学生分数
SELECT id ,`score` FROM student
WHERE id!=1

SELECT id ,`score` FROM student
WHERE NOT id=1

模糊查询 : 比较运算符

运算符 语法 描述
IS NULL a is null 如果操作符为null,结果为真
IS NOT NULL a is not null 如果操作符为 not 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.....其中的某一个值中,结果为真
-- 查询姓张的同学
-- LIKE结合  %(代表0到任意个字符)    _(一个字符)
SELECT `id`,`name` FROM student
WHERE name LIKE '张%'

-- 查询姓张的同学,名字只有两位的
SELECT `id`,`name` FROM student
WHERE name LIKE '张_'

-- 查询姓张的同学,名字只有三位的
SELECT `id`,`name` FROM student
WHERE name LIKE '张__'

-- 查询名字中间有子字的同学  %子%
SELECT `id`,`name` FROM student
WHERE name LIKE '%子%'

-- ===========IN==========
-- 查询指定的学生
SELECT `id`,`name` FROM student
WHERE id in (1,2,3)

-- 查询在北京的学生
SELECT `id`,`name` FROM student
WHERE `address` in ('北京','漯河');

-- ========null    not null===

-- 查询地址为空的学生
SELECT `id`,`name` FROM student
WHERE address='' or address is NULL ;

-- 查询有出生日期的同学  (不为空)
SELECT `id`,`name` FROM student
WHERE birthday is not NULL

-- 查询没有出生日期的同学
SELECT `id`,`name` FROM student
WHERE birthday is NULL

联表查询 待学*

分页查询和排序

排序

-- ========== 分页 LIMIT 和排序 ORDER BY===========

-- 排序: 升序 ASC , 降序 	DESC
-- ORDER BY 通过哪个字段排序
-- 查询的结果根据 成绩降序 排序
SELECT `id`,`name`,`score`
FROM student
ORDER BY score DESC

分页

-- ========== 分页 LIMIT 和排序 ORDER BY===========

-- 排序: 升序 ASC , 降序 	DESC
-- ORDER BY 通过哪个字段排序
-- 查询的结果根据 成绩降序 排序
SELECT `id`,`name`,`score`
FROM student
ORDER BY score DESC


-- 为什么要分页
-- 缓解数据库压力,给人的体验更好

-- 分页,每页只显示五条数据
-- 语法: LIMIT 当前页,页面的大小
-- 第一页 LIMIT 0,5           (1-1)*5
-- 第二页 LIMIT 5,5           (2-1)*5
-- 第三页 LIMIT 10,5          (3-1)*5
-- 第N页 LIMIT 0,5            (n-1)*pageSize,pageSize
-- [pageSize:页面大小]
-- [(n-1)*pageSize起始值]
-- [n:当前页]
-- [数据总数/页面大小 = 总页数]
SELECT `id`,`name`,`score`
FROM student
LIMIT 5,5

语法:LIMIT(查询起始下标,pageSize)

子查询 待学*

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

MySQL函数

常用函数


聚合函数(常用)


事务

索引

权限管理和备份

规范数据库设计

JDBC(重点)

数据库驱动

JDBC

SUN公司为了简化开发人员的(对数据库的统一)操作,提供了一个(java操作数据库的)规范,俗称JDBC

第一个JDBC程序

1.创建测试数据库

CREATE TABLE `student` (
  `id` int(5) NOT NULL AUTO_INCREMENT COMMENT '学号',
  `name` varchar(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
  `pwd` varchar(20) NOT NULL DEFAULT '123456' COMMENT '密码',
  `sex` varchar(2) NOT NULL DEFAULT '女' COMMENT '性别',
  `birthday` datetime DEFAULT NULL COMMENT '出生日期',
  `address` varchar(100) DEFAULT NULL COMMENT '家庭住址',
  `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  `score` int(5) DEFAULT NULL COMMENT '分数',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;

INSERT INTO `student` VALUES (1, '迪迦', '1234', '男', '2020-12-14 00:00:00', '郑州市', '766656302@qq.com', 60);
INSERT INTO `student` VALUES (2, '曾小贤', '123456', '女', '2020-12-16 14:51:38', '北京', NULL, 70);
INSERT INTO `student` VALUES (3, '吕小布', '123456', '女', '2020-12-01 14:51:43', '武汉', NULL, 80);
INSERT INTO `student` VALUES (4, '斯内克', '123456', '女', NULL, '杭州', NULL, 100);
INSERT INTO `student` VALUES (5, '南子旭', '123456', '女', NULL, '上海', NULL, 140);
INSERT INTO `student` VALUES (6, '张三', '123456', '女', NULL, '广州', NULL, 100);
INSERT INTO `student` VALUES (7, '张大炮', '123456', '女', NULL, '漯河', NULL, 100);
INSERT INTO `student` VALUES (8, '匿名', '123456', '女', NULL, '广西', NULL, 100);
INSERT INTO `student` VALUES (9, '匿名', '123456', '女', NULL, '洛阳', NULL, 100);
INSERT INTO `student` VALUES (10, '匿名', '123456', '女', NULL, NULL, NULL, 100);
INSERT INTO `student` VALUES (11, '匿名', '123456', '女', NULL, NULL, NULL, NULL);
INSERT INTO `student` VALUES (12, '南子旭', '123456', '男', NULL, NULL, NULL, NULL);

2.导入jar包

3.编写测试代码

package com.soft.test;

import java.sql.*;

public class TestStudent {
    public static void main(String[] args) {
        ResultSet resultSet = null;
        Connection con = null;
        Statement stmt = null;
        try {
            //1.加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");

            //2.用户信息和url
            String url = "jdbc:mysql://localhost:3306/school?serverTimezone=GMT";
            String userName = "root";
            String pwd = "root";

            //3.连接成功,数据库对象 Connection 代表数据库
            con = DriverManager.getConnection(url, userName, pwd);

            //4.执行SQL的对象 Statement
            stmt = con.createStatement();

            //5.执行SQK的对象去执行SQL
            String sql = "insert into student(name,pwd,sex) values('南子旭','123456','男')";
            String sql1 = "SELECT * FROM student";

//            int i = stmt.executeUpdate(sql);
//            if (i == 1){
//                System.out.println("添加成功!");
//            }else {
//                System.out.println("添加失败!");
//            }

            resultSet = stmt.executeQuery(sql1); //executeQuery返回一个结果集,结果集中封装了我们全部的查询结果
            System.out.println(resultSet);
            while (resultSet.next()){
                String name = resultSet.getString(1);
                String name2 = resultSet.getString(2);
                String name3 = resultSet.getString(3);
                String name4 = resultSet.getString(4);
                String name5 = resultSet.getString(5);
                String name6 = resultSet.getString(6);
                String name7 = resultSet.getString(7);
                System.out.println(name+name2+name3+name4+name5+name6+name7);
            }

        } catch (ClassNotFoundException e) {
            System.out.println("驱动加载失败!");
            e.printStackTrace();
        } catch (SQLException throwables) {
            System.out.println("数据库连接失败!");
            throwables.printStackTrace();
        }finally {
            if (resultSet != null){
                try {
                    resultSet.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (stmt != null){
                try {
                    resultSet.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (con != null){
                try {
                    resultSet.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }


    }
}

步骤总结:

  1. 加载驱动
  2. 定义用户信息和url
  3. 连接数据库DriverManager.getConnection
  4. 获得执行sql对象 Statement
  5. 获得返回的结果集
  6. 释放连接

Statement对象

DriverManager

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

URL

String url = "jdbc:mysql://localhost:3306/school?serverTimezone=GMT";

Statement 执行SQL的对象 PreparedStatement 执行SQL的对象

 String sql1 = "SELECT * FROM student"; //创建SQL语句
 
 Statement接口提供了三种执行SQL语句的方法:executeQuery 、executeUpdate  
   和execute  
    1、ResultSet executeQuery(String sqlString):执行查询数据库的SQL语句  
        ,返回一个结果集(ResultSet)对象。  
     2、int executeUpdate(String sqlString):用于执行INSERT、UPDATE或  
        DELETE语句以及SQL DDL语句,如:CREATE TABLE和DROP TABLE等  
     3、execute(sqlString):用于执行返回多个结果集、多个更新计数或二者组合的  
        语句。  
   具体实现的代码:  
          ResultSet rs = stmt.executeQuery("SELECT * FROM ...") ;  
    int rows = stmt.executeUpdate("INSERT INTO ...") ;  
    boolean flag = stmt.execute(String sql) ;  

ResultSet

resultSet.getObject //在不知道类型的情况下使用
resultSet.getString //知道类型的情况下使用
    
resultSet.next() //移动到下一个数据

释放资源

resultSet.close();
resultSet.close();
resultSet.close();

代码实现

  1. 提取工具类

    package com.soft.util;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.sql.*;
    import java.util.*;
    
    public class DbUtil {
        private static String driver = null;
        private static String url = null;
        private static String userName = null;
        private static String pwd = null;
    
        static Connection conn = null;
        static PreparedStatement stmt = null;
        static ResultSet rs = null;
    
        static {
            try {
                InputStream in = DbUtil.class.getClassLoader().getResourceAsStream("db.properties");
                Properties properties = new Properties();
                properties.load(in);
    
                driver = properties.getProperty("driver");
                url = properties.getProperty("url");
                userName = properties.getProperty("userName");
                pwd = properties.getProperty("pwd");
    
                //1.驱动只用加载一次
                Class.forName(driver);
    
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
    
                System.err.println("驱动加载异常!");
                e.printStackTrace();
            }
        }
    
        //获取连接
        public static Connection getConnection() throws SQLException {
            return DriverManager.getConnection(url, userName, pwd);
        }
    
        //释放资源
        public static void release(Connection conn, Statement stmt, ResultSet rs) {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    
        //封装增删改方法
        public static void updateOrInsertOrDelete(String sql, Object... objs) {
            try {
                stmt = getConnection().prepareStatement(sql);
    
                int i = 1;
                for (Object obj : objs
                ) {
                    stmt.setObject(i++, obj);
                }
    
                int m = stmt.executeUpdate();
                if (m > 0) {
                    System.out.println("操作成功!");
                } else {
                    System.out.println("操作失败!");
                }
    
    
            } catch (SQLException throwables) {
                System.err.println("处理SQL出现异常!");
                throwables.printStackTrace();
            }finally {
                release(conn, stmt, rs);
            }
        }
    
        //封装查询方法
        public static List<LinkedHashMap<String, String>> query(String sql, Object... objs) {
            List<LinkedHashMap<String, String>> list = null;
            LinkedHashMap<String, String> map = null;
            try {
                stmt = getConnection().prepareStatement(sql);
                int i = 1;
                for (Object obj : objs
                ) {
                    stmt.setObject(i++, obj);
                }
    
                rs = stmt.executeQuery();
    //            while (rs.next()){
    //                for (int j = 1; j < objs.length; j++) {
    //                    System.out.println(rs.getString(j));
    //                }
    //            }
    
                ResultSetMetaData metaData = rs.getMetaData();
    //            System.out.println(metaData);
                int count = metaData.getColumnCount();
    
                list = new ArrayList<>();
                while (rs.next()) {
                    for (int j = 1; j <= count; j++) {
    
                        map = new LinkedHashMap<>();
                        String columnName = metaData.getColumnName(j);
    
                        String value = rs.getString(j);
    
                        map.put(columnName, value);
    
                        list.add(map);
    
    
                    }
                }
    
    
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            } finally {
                release(conn, stmt, rs);
            }
            return list;
        }
    }
    
    driver = com.mysql.cj.jdbc.Driver
    url = jdbc:mysql://localhost:3306/school?serverTimezone=GMT
    userName = root
    pwd = root
    
  2. 增加方法

public class TestInsert {
    public static void main(String[] args) {
        Connection connection = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            connection = DbUtil.getConnection(); //获取数据库连接
            stmt = connection.createStatement(); //获得SQL的执行对象
            String sql = "insert into student(name,pwd,sex) values('南子旭','123456','男')";

            int i = stmt.executeUpdate(sql);
            if (i > 0){
                System.out.println("插入成功!");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            DbUtil.release(connection,stmt,rs);
        }


    }
}
  1. 查询方法

    public class TestSelect {
        public static void main(String[] args) {
            Connection conn = null;
            Statement stmt = null;
            ResultSet rs = null;
    
            try {
                conn= DbUtil.getConnection();
                stmt = conn.createStatement();
    
                String sql = "SELECT * FROM student";
                rs = stmt.executeQuery(sql);
                while (rs.next()){
                    System.out.println(rs.getString(1));
                    System.out.println(rs.getString(2));
                    System.out.println(rs.getString(3));
                    System.out.println(rs.getString(4));
                }
    
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
                DbUtil.release(conn,stmt,rs);
            }
    
        }
    }
    

SQL注入问题

sql存在漏洞,会被攻击存在数据泄露,SQL会被拼接 or

package com.soft.test;

import com.soft.util.DbUtil;

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

public class Sql {
    public static void main(String[] args) {
//        login("迪迦","1234");
        login("'or' 1=1","'or' 1=1");

    }

    public static void login(String name,String pwd){
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        try {
            conn= DbUtil.getConnection();
            stmt = conn.createStatement();

            String sql = "SELECT * FROM student where name='"+name+"' and pwd ='"+pwd+"'";
            rs = stmt.executeQuery(sql);
            while (rs.next()){
                System.out.println(rs.getString(1));
                System.out.println(rs.getString(2));
                System.out.println(rs.getString(3));
                System.out.println(rs.getString(4));
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            DbUtil.release(conn,stmt,rs);
        }
    }
}

PreparedStatement对象

preparedStatement可以防止SQL注入,效率更高!

  1. 新增

    package com.soft.test2;
    
    import com.soft.util.DbUtil;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    import java.util.Date;
    
    public class TestInsert {
        public static void main(String[] args) {
            Connection conn = null;
            PreparedStatement stmt = null;
            try {
                conn = DbUtil.getConnection();
    
                String sql = "insert into student(name,pwd,sex,birthday) values(?,?,?,?)";
                stmt = conn.prepareStatement(sql);
    
                //手动给参数赋值
                stmt.setString(1,"雷军");
                stmt.setString(2,"123456");
                stmt.setString(3,"男");
                //注意点: sql.Date  数据库 java.sql.Date
    //                   util.Date  Java  new Date().getTime() 获得时间戳
                stmt.setDate(4,new java.sql.Date(new Date().getTime()));
    
                //执行
                int i = stmt.executeUpdate();
                if (i > 0){
                    System.out.println("插入成功!");
                }
    
    
    
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
                DbUtil.release(conn,stmt,null);
            }
        }
    }
    
  2. 删除

    package com.soft.test2;
    
    import com.soft.util.DbUtil;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    import java.util.Date;
    
    public class TestDelete {
        public static void main(String[] args) {
            Connection conn = null;
            PreparedStatement stmt = null;
            try {
                conn = DbUtil.getConnection();
    
                String sql = "delete from student where id = ?";
                stmt = conn.prepareStatement(sql);
    
                //手动给参数赋值
                stmt.setInt(1,10);
    
    
                //执行
                int i = stmt.executeUpdate();
                if (i > 0){
                    System.out.println("删除成功!");
                }
    
    
    
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
                DbUtil.release(conn,stmt,null);
            }
        }
    }
    
  3. 更新

    package com.soft.test2;
    
    import com.soft.util.DbUtil;
    
    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 stmt = null;
            try {
                conn = DbUtil.getConnection();
    
                String sql = "update student set name = ? where id=?;";
                stmt = conn.prepareStatement(sql);
    
                //手动给参数赋值
                stmt.setString(1, "南子旭");
                stmt.setInt(2,10);
    
                //执行
                int i = stmt.executeUpdate();
                if (i > 0) {
                    System.out.println("更新成功!");
                }
    
    
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            } finally {
                DbUtil.release(conn, stmt, null);
            }
        }
    }
    
  4. 查询

    package com.soft.test2;
    
    import com.soft.util.DbUtil;
    
    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 stmt = null;
            ResultSet rs = null;
            try {
                conn = DbUtil.getConnection();
    
                String sql = "select * from student where id = ?;";
                stmt = conn.prepareStatement(sql);
    
                stmt.setInt(1,1);
    
                //执行
                rs = stmt.executeQuery();
                if (rs.next()){
                    System.out.println(rs.getString(3));
                }
    
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
                DbUtil.release(conn,stmt,rs);
            }
        }
    }
    
  5. 防止SQL注入

package com.soft.test2;

import com.soft.util.DbUtil;

import java.sql.*;

public class Sql {
    public static void main(String[] args) {
//        login("迪迦","1234");
        login("'' or 1=1","'' or 1=1");

    }

    public static void login(String name,String pwd){
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;

        try {
            conn= DbUtil.getConnection();

            //PreparedStatement 防止SQL注入的本质,把传递进来的参数当做字符
            //假设其中存在转义字符,会被直接转义 比如'
            String sql = "SELECT * FROM student where name = ? and pwd = ?";
            stmt = conn.prepareStatement(sql);
            stmt.setString(1,name);
            stmt.setString(2,pwd);

            rs = stmt.executeQuery();
            while (rs.next()){
                System.out.println(rs.getString(1));
                System.out.println(rs.getString(2));
                System.out.println(rs.getString(3));
                System.out.println(rs.getString(4));
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            DbUtil.release(conn,stmt,rs);
        }
    }
}

使用IDEA连接数据库

连接成功后可以选择数据库

image-20210121232151279

事务

要么都成功,要么都失败

ACID原则

原子性:要么全部完成,要么都不完成

一致性:总数不变

隔离性:多个进程互不干扰

  • 隔离性的问题
    • 脏读:一个事物读取了另一个没有提交的事务
    • 不可重复读:在同一事务内,重复读取表中的数据,表数据发生了改变
    • 虚度(幻读):在一个事务内,读取到了别人插入的数据,导致前后读出来的结果不一致

持久性:一单提交不可逆,持久化到数据库了

代码实现

  1. 开启事务conn.setAutoCommit(false);
  2. 一组业务执行完毕,提交事务
  3. 可以在catch语句中显示定义回滚语句,但默认失败就会回滚
package com.soft.test3;

import com.soft.util.DbUtil;

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

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

        try {
            conn= DbUtil.getConnection();
            //关闭数据库的自动提交功能
            conn.setAutoCommit(false); // 开启事务

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

//            int x = 1/0;

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

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


        } catch (SQLException throwables) {
//            try {
//                conn.rollback(); //如果失败则回滚事务
//            } catch (SQLException e) {
//                e.printStackTrace();
//            }
            throwables.printStackTrace();
        }finally {
            DbUtil.release(conn,stmt,rs);
        }
    }
}

数据库连接池

数据库连接 --- 执行完毕 --- 释放

连接 -- 释放 十分浪费系统资源

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

最小连接数:

最大连接数:

等待超时:

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

开源数据源实现

DBCP

C3P0

Druid:阿里巴巴

使用了这些数据库连接池之后,我们在项目开发中就不需要编写连接数据库的代码了!

BDCP

需要用到的jar包

commons-dbcp-1.4.jar

commons-pool2-2.9.0.jar

posted @ 2021-09-17 17:33  Mr_NanZiXu  阅读(44)  评论(0)    收藏  举报