Java学习笔记(No.25)

Java之MySQL(No.25)

1、常规软件开发分类(General Software Development Classification)

1.1、前台(Reception)

也称为“前端(Front-End)”,一般为页面,主要显示数据

1.2、后台(Backstage)

也称为“后端(Back-End)”,一般为连接点,连接前端(控制视图跳转或传递前端数据)以及连接数据库(JDBC)

1.3、数据库(DataBase)

一般为后台存储数据(如:txt、excel、word等)

1.4、注意事项(Matters Needing Attention)

  • 1.4.1、初级程序员:只会写业务代码,以及数据库的CRUD操作(即,增加[Create]、检索[Retrieve]、更新[Update]和删除[Delete])
  • 1.4.2、中级程序员:在初级程序员基础上,还会操作系统、数据结构与算法
  • 1.4.3、高级程序员:在中级程序员基础上,还会离散数学、数字电路、体系结构、编译原理以及实战经验

2、数据库(DataBase)

即“数据仓库”,是一种可以存储数据与管理数据的软件。其一般分为两种(关系型数据库与非关系型数据库)

2.1、关系型数据库(Relational DataBase)

一般存储行列数据,通过表与表之间、行与列之间的关系来存储数据

  • 2.1.1、MySQL
  • 2.1.2、Oracle
  • 2.1.3、SQL Server
  • 2.1.4、DB2
  • 2.1.5、SQLite

2.2、非关系型数据库(Not Only SQL)

一般存储对象数据,通过对象自身的属性来存储数据

  • 2.2.1、Redis
  • 2.2.2、MongDB

3、MySQL数据库管理系统(MySQL DataBase Management System)

MySQL是一种关系型数据库管理系统(DataBase Management System)软件

MySQL是由瑞典MySQL AB公司开发,现属于Oracle旗下产品

MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言。且由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型或大型网站的开发都选择MySQL作为网站数据库

4、MySQL5.7非安装版配置(MySQL5.7 Non Installation Version Configuration)

4.1、软件下载

官网下载地址(https://dev.mysql.com/downloads/mysql/5.7.html)

4.2、软件配置

  • 4.2.1、解压已下载软件压缩包,将解压文件放到自定义环境目录路径下(如"E:\Environment\Java\MySQL\mysql-5.7.35")

  • 4.2.2、配置软件的系统环境变量,如下图所示

    配置软件的系统环境变量

  • 4.2.3、在自定义环境目录路径下(如"E:\Environment\Java\MySQL\mysql-5.7.35")新建ini配置文件(其名称为“my.ini”,即“E:\Environment\Java\MySQL\mysql-5.7.35\my.ini”),其配置内容如下所示

    [mysql]
    # 设置mysql客户端默认字符集
    # default-character-set=utf8
    [mysqld]
    skip-grant-tables
    # 设置3306端口
    port = 3306
    # 设置mysql的安装目录
    basedir=E:\Environment\Java\MySQL\mysql-5.7.35\
    # 设置mysql数据库的数据的存放目录
    datadir=E:\Environment\Java\MySQL\mysql-5.7.35\data\
    # 允许最大连接数
    # max_connections=20
    # 服务端使用的字符集默认为8比特编码的latin1字符集
    # character-set-server=utf8
    # 创建新表时将使用的默认存储引擎
    # default-storage-engine=INNODB
    
  • 4.2.4、启动管理员模式下的CMD命令窗口,然后输入CMD命令(mysqld install),安装MySQL服务,如下图所示

    安装MySQL服务

  • 4.2.5、输入CMD命令(mysqld --initialize-insecure --user=mysql),初始化MySQL数据库文件,如下图所示

    初始化MySQL数据库文件

  • 4.2.6、输入CMD命令(net start mysql),启动MySQL服务,如下图所示

    启动MySQL服务

  • 4.2.7、输入CMD命令(mysql -uroot -p),首次登录MySQL,如下图所示

    首次登录MySQL

  • 4.2.8、分别输入CMD命令1(use mysql;)、CMD命令2(update user set authentication_string=password(“123456”) where user=‘root’😉、CMD命令3(flush privileges;),修改MySQL登录密码,如下图所示

    修改MySQL登录密码

  • 4.2.9、修改ini配置文件(即“E:\Environment\Java\MySQL\mysql-5.7.35\my.ini”),其内容如下所示

    [mysql]
    # 设置mysql客户端默认字符集
    # default-character-set=utf8
    [mysqld]
    # 将“skip-grant-tables”注释掉后代表登录MySQL时必须验证密码,否则登录MySQL时不验证密码
    # skip-grant-tables
    # 设置3306端口
    port = 3306
    # 设置mysql的安装目录
    basedir=E:\Environment\Java\MySQL\mysql-5.7.35\
    # 设置mysql数据库的数据的存放目录
    datadir=E:\Environment\Java\MySQL\mysql-5.7.35\data\
    # 允许最大连接数
    # max_connections=20
    # 服务端使用的字符集默认为8比特编码的latin1字符集
    # character-set-server=utf8
    # 创建新表时将使用的默认存储引擎
    # default-storage-engine=INNODB
    
  • 4.2.10、输入CMD命令(exit),退出MySQL登录,如下图所示

    退出MySQL登录

  • 4.2.11、输入CMD命令(net stop mysql),停止MySQL服务,如下图所示

    停止MySQL服务

  • 4.2.12、输入CMD命令(net start mysql),重新启动MySQL服务,如下图所示

    重新启动MySQL服务

  • 4.2.13、输入CMD命令(mysql -uroot -p123456),重新登录MySQL(修改密码已生效),如下图所示

    重新登录MySQL(修改密码已生效)

5、SQLyog下载、安装、配置(SQLyog Download And Installation And Configuration)

参考网址(http://www.xue51.com/soft/2982.html)

6、SQLyog使用(SQLyog Use)

参考网址(https://blog.csdn.net/su2231595742/article/details/107967198)

7、四大SQL语言(Four SQL Languages)

7.1、数据查询语言(DQL,Data Query Language)

数据查询语言DQL基本结构是由SELECT子句,FROM子句,WHERE子句组成的查询块:SELECT <字段名表>FROM <表或视图名>WHERE <查询条件>

7.2、数据操纵语言(DML,Data Manipulation Language)

数据操纵语言DML主要有三种形式:1、插入(INSERT);2、更新(UPDATE);3、删除(DELETE)

7.3、数据定义语言(DDL,Data Definition Language)

数据定义语言DDL用来创建数据库中的各种对象,如表、视图、索引、同义词、聚簇(CREATE TABLE / VIEW / INDEX / SYN / CLUSTER)等。且DDL操作是隐性提交的,不能rollback

7.4、数据控制语言(DCL,Data Control Language)

数据控制语言DCL用来授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视等,如下所示

  • 7.4.1、GRANT:授权

  • 7.4.2、ROLLBACK [WORK] TO [SAVEPOINT]:回退到某一点。ROLLBACK回滚命令使数据库状态回到上次最后提交的状态。其格式为:SQL>ROLLBACK

  • 7.4.3、 COMMIT [WORK]:提交。在数据库的插入、删除和修改操作时,只有当事务在提交到数据库时才算完成。在事务提交前,只有操作数据库的这个人才能有权看到所做的事情,别人只有在最后提交完成后才可以看到。提交数据有三种类型:显式提交、隐式提交及自动提交。下面分别说明这三种类型

    • 7.4.3.1、显式提交

      用COMMIT命令直接完成的提交为显式提交。其格式为:SQL>COMMIT

    • 7.4.3.2、隐式提交

      用SQL命令间接完成的提交为隐式提交。这些命令是:ALTER,AUDIT,COMMENT,CONNECT,CREATE,DISCONNECT,DROP,EXIT,GRANT,NOAUDIT,QUIT,REVOKE,RENAME

    • 7.4.3.3、自动提交

      若把AUTOCOMMIT设置为ON,则在插入、修改、删除语句执行后,系统将自动进行提交,这就是自动提交。其格式为:SQL>SET AUTOCOMMIT ON

8、操作MySQL数据库(Operation MySQL DataBase)

MySQL关键字不区分大小写,且单行注释符号为--,多行注释为/**/

8.1、创建数据库

CREATE DATABASE IF NOT EXISTS db_1;

8.2、删除数据库

DROP DATABASE IF EXISTS db_1;

8.3、使用数据库

-- 使用反引号标注表名或字段名
USE `test`;

8.4、查看数据库

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

9、MySQL数据库列类型(MySQL DataBase Column Type)

9.1、数值

名称描述长度备注
tinyint十分小的整数1个字节
smallint较小的整数2个字节
mediumint中等大小的整数3个字节
int标准的整数4个字节常用
bigint较大的整数8个字节
float单精度浮点数4个字节
double双精度浮点数8个字节存在精度问题,一般不适用于金融计算
decimal字符串形式的浮点数16个字节一般适用于金融计算

9.2、字符串

名称描述长度大小范围备注
char固定大小字符串0~255
varchar可变大小字符串0~65535常用
tinytext微型文本0~255二进制存储
text文本串0~65535二进制存储,保存大文本

9.3、日期时间

名称描述备注
date日期格式(如:YYYY-MM-DD)
time时间格式(如:HH:mm:ss)
datetime日期时间格式(如:YYYY-MM-DD HH:mm:ss)常用
timestamp时间戳(即,从1970年1月1日到现在的毫秒数,全世界统一)较常用
year年份

9.4、null

即,空值,或没有值,或未知,且不要使用null进行运算,其结果只能为null

10、MySQL数据库字段属性(MySQL DataBase Field Properties)

10.1、unsigned

即,无符号整数,不能为负数

10.2、zerofill

即,数据不足的位数,使用0来填充<如字段为int(2)时,若输入数值1,则最终数值自动填充为01>

10.3、自增

即,通常用来设计唯一的主键,且必须为整数,其每次生成数值会自动累加

10.4、非空

即,不允许数据为空

10.5、默认

即,数据默认值

10.6、注意事项

一般每个表都会存在以下5个字段,用来表示一个记录存在的意义,如下所示:
1、主键(id,唯一标识)
2、乐观锁(version,版本)
3、伪删除(is_delete,标志位)
4、创建时间(gmt_create,创建时间)
5、修改时间(gmt_update,修改时间)

11、创建MySQL数据库及表(Create MySQL DataBase And Table)

其sql语句,如下所示

-- 创建school数据库
CREATE DATABASE IF NOT EXISTS `school` CHARACTER SET utf8 COLLATE utf8_general_ci;
-- 创建student数据表
CREATE TABLE IF NOT EXISTS `student`(
	`id` INT(10) NOT NULL AUTO_INCREMENT COMMENT '学号',
	`name` VARCHAR(10) NOT NULL DEFAULT '匿名' COMMENT '姓名',
	`pwd` VARCHAR(20) NOT NULL DEFAULT '12321' 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 COLLATE=utf8_general_ci COMMENT '创建学生数据表';
-- 查看创建school数据库的sql语句
SHOW CREATE DATABASE `school`;
-- 查看创建student数据表的sql语句
SHOW CREATE TABLE `student`;
-- 显示student数据表结构
DESC `student`;

12、MySQL数据表类型(MySQL Data Table Type)

MySQL中所有数据库文件都存在data目录下,一个文件夹对应一个数据库,其本质还是文件的存储

12.1、MySQL引擎(MySQL Engine)

MySQL引擎,一般常用“MYISAM引擎”与“INNODB引擎”

12.1.1、物理存储区别(Physical Storage Differences)
  • 12.1.1.1、MYISAM引擎

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

  • 12.1.1.2、INNODB引擎

    在data目录下,其数据库表中有三个文件,如下所示

    • 12.1.1.2.1、*.frm文件(表结构的定义文件)
    • 12.1.1.2.2、*.myd文件(数据文件)
    • 12.1.1.2.3、*.myi文件(索引文件)
12.1.2、功能使用区别(Function Use Differences)
功能MYISAM引擎INNODB引擎
事物处理不支持支持
数据行锁定不支持支持
外键约束不支持支持
全文索引支持不支持
12.1.3、优缺点(Advantages And Disadvantages)
数据库引擎优点缺点
MYISAM节约空间(空间较小),速度较快安全性不高,不支持事务处理及多表用户操作
INNODB安全性高,支持事务处理及多表用户操作空间较大(约为MYISAM空间2倍),速度较慢

12.2、MySQL字符集(MySQL Character Set)

-- 默认MySQL字符集编码为“Latin1”,不支持中文,需单独设定,目前有2种方式,如下所示。
-- 方式1(推荐使用,不会随不同环境的改变而有差异):直接在SQL语句中设置数据库表字符集编码(如“CHARSET=utf8”);
-- 方式2(推荐使用,可能会随不同环境的改变而有差异):直接在"my.ini"配置文件中设置MySQL默认字符集编码(如“character-set-server=utf8”);

13、修改删除MySQL数据表(Modify And Delete MySQL Data Table)

13.1、修改数据表(Modify Data Table)

-- 修改数据表名称:ALTER TABLE `旧表名` RENAME AS `新表名`
ALTER TABLE `student` RENAME AS `student1`;
-- 增加数据表字段:ALTER TABLE `表名` ADD `列名` 列属性
ALTER TABLE `student1` ADD `age` INT(3);
-- 修改数据表字段列属性(修改约束):ALTER TABLE `表名` MODIFY `列名` 列属性
ALTER TABLE `student1` MODIFY `age` VARCHAR(11);
-- 修改数据表字段列名称及列属性(重命名+修改约束):ALTER TABLE `表名` CHANGE `旧列名` `新列名` 列属性
ALTER TABLE `student1` CHANGE `age` `age1` INT(5);
-- 删除数据表字段:ALTER TABLE `表名` DROP `列名`
ALTER TABLE `student1` DROP `age1`;

13.2、删除数据表(Delete Data Table)

-- 删除数据表(若存在再删除,否则不删除):ALTER TABLE `表名` DROP `列名`
DROP TABLE IF EXISTS `student1`;

14、MySQL数据管理(MySQL Data Management)

14.1、外键(Foreign Key)

-- 方式1:在创建表的时候,增加外键约束
-- 创建grade表
CREATE TABLE IF NOT EXISTS `grade`(
`gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT '年级id',
`gradename` VARCHAR(50) NOT NULL COMMENT '年级名称',
PRIMARY KEY(`gradeid`) COMMENT '主键gradeid'
)ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT '创建年级表';
-- 创建student表,增加外键约束
CREATE TABLE IF NOT EXISTS `student`(
	`id` INT(10) NOT NULL AUTO_INCREMENT COMMENT '学号',
	`name` VARCHAR(10) NOT NULL DEFAULT '匿名' COMMENT '姓名',
	`pwd` VARCHAR(20) NOT NULL DEFAULT '12321' 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 '电子邮箱',
	`gradeid` INT(10) NOT NULL COMMENT '学生年级id',
	PRIMARY KEY(`id`) COMMENT '主键id',
	KEY `FK_gradeid`(`gradeid`) COMMENT '外键gradeid',
	CONSTRAINT `FK_gradeid` FOREIGN KEY(`gradeid`) REFERENCES `grade`(`gradeid`) 
)ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT '创建学生表';

/*
-- 方式2:在创建表完后,增加外键约束
-- 创建grade表
CREATE TABLE IF NOT EXISTS `grade`(
`gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT '年级id',
`gradename` VARCHAR(50) NOT NULL COMMENT '年级名称',
PRIMARY KEY(`gradeid`) COMMENT '主键gradeid'
)ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT '创建年级表';
-- 创建student表
CREATE TABLE IF NOT EXISTS `student`(
	`id` INT(10) NOT NULL AUTO_INCREMENT COMMENT '学号',
	`name` VARCHAR(10) NOT NULL DEFAULT '匿名' COMMENT '姓名',
	`pwd` VARCHAR(20) NOT NULL DEFAULT '12321' 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 '电子邮箱',
	`gradeid` INT(10) NOT NULL COMMENT '学生年级id',
	PRIMARY KEY(`id`) COMMENT '主键id'
)ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT '创建学生表';
-- 创建表后增加外键约束:ALTER TABLE `引用表` ADD CONSTRAINT `约束名` FOREIGN KEY(`外键列`) REFERENCES `被引用表`(`被引用列`)
ALTER TABLE `student` ADD CONSTRAINT `FK_gradeid` FOREIGN KEY(`gradeid`) REFERENCES `grade`(`gradeid`);
*/

/*
注意事项:
1、删除有外键关系表时,必须先删除引用表(从表),再删除被引用表(主表)。
2、不建议使用外键关系表,以防连接多张表影响效率,最好由程序内部业务去实现。
3、最好的数据表就是只用来存储数据,只有行(数据)与列(字段),没有其他约束条件。
*/

14.2、添加数据(Add Data)

-- 添加(插入)语句:INSERT INTO `表名`(`列1`,`列2`,...) VALUES(列1值1,'列2值1'),(列1值2,'列2值2'),...;
-- 插入单行数据时,若不写表字段,则自动一一对应插入数值
INSERT INTO `grade` VALUES(1,'1年级');
-- 插入单行数据时,若写表字段,则表字段需一一对应插入数值
INSERT INTO `grade`(`gradename`) VALUES('2年级');
-- 插入多行数据时,若写表字段,则表字段需一一对应插入数值
INSERT INTO `grade`(`gradeid`,`gradename`) VALUES(3,'3年级'),(4,'4年级');

14.3、修改数据(Modify Data)

-- 修改(更新)语句:UPDATE `表名` SET `列1`=列1值,`列2`='列2值',... WHERE 条件;
-- 修改所有的年级名称(未指定条件)
UPDATE `grade` SET `gradename`='100年级';
-- 修改年级id为1的年级名称
UPDATE `grade` SET `gradename`='11年级' WHERE `gradeid`=1;
-- 修改年级id为1的年级id、年级名称
UPDATE `grade` SET `gradeid`=1,`gradename`='111年级' WHERE `gradeid`=1;

14.4、删除数据(Delete Data)

-- 删除数据语句:
-- 1、DELETE命令:DELETE FROM `表名` WHERE 条件
-- 删除指定数据
DELETE FROM `grade` WHERE `gradeid`=4;
-- 删除表中所有数据(未指定条件)
DELETE FROM `grade`;
-- 2、TRUNCATE命令:TRUNCATE `表名`,其作用为“完全清空一个数据表,表的结构与索引约束不会变”。
TRUNCATE `grade`;
/*
一、DELETE命令与TRUNCATE命令区别:
1、相同点:都能清空数据表数据,且都不会删除表结构。
2、不同点:2.1、TRUNCATE命令会重新设置“自增列”(计数器会归零);2.2、TRUNCATE命令不会影响事务。
二、DELETE清空表数据后,重启数据库的特殊现象:
1、若数据库引擎为INNODB,则自增列会重新从1开始计数(存在内存中,断电即失);
2、若数据库引擎为MYISAM,则自增列会继续从上一个自增量+1开始计数(存在文件中,不会丢失);
*/

14.5、查询数据(Query Data)

查询(选择)数据语句:数据库中最核心的SQL语言,使用频率最高的SQL语句(一般80%的操作都是它)

14.5.1、查询SQL完整语法(Query SQL Complete Grammar)
-- Select完整语法:
SELECT [ALL | DISTINCT]
{*|table.*|[table.field1[AS alias1][,table.field2[AS alias2][,...]]}
FROM table_name1 [AS table_alias1]
[LEFT|RIGHT|INNER JOIN table_name2 [AS table_alias2]] -- 联合查询
[WHERE ...] -- 指定结果满足的条件
[GROUP BY ...] -- 指定结果按照哪几个字段来分组
[HAVING ...] -- 过滤分组的记录必须满足的次要条件
[ORDER BY ...] -- 指定查询记录按一个或多个条件排序
[LIMIT {[OFFSET,]ROW_COUNT|row_countoffset OFFSET}]; -- 指定查询的记录从哪条到哪条
-- 注意事项:以上语法里面的中括号“[]”代表可选的参数,花括号“{}”代表必选的参数。
14.5.2、查询指定字段(Query Specified Fields)
-- 查询所有字段
SELECT * FROM `student`;
-- 查询指定字段,且给每一个字段取一个别名
SELECT `id`,`name`,`pwd` FROM `student`;
-- 查询指定字段拼接后的新字段,且取一个别名
SELECT CONCAT(`name`,'生日:',`birthday`) AS '学生生日' FROM `student`;
-- 去重:查询唯一的指定字段
SELECT DISTINCT `name` FROM `student`;
-- 查询SQL表达式:字段列、文本值、NULL、函数、计算表达式、系统变量、...
SELECT `address` AS '地址' FROM `student`; -- 查询地址(字段列)
SELECT '12321'; -- 查询指定字符串(文本值)
SELECT NULL; -- 查询指定值NULL(NULL)
SELECT VERSION(); -- 查询系统版本(函数)
SELECT 10*2-1 AS '计算结果'; -- 用来计算(计算表达式)
SELECT @@auto_increment_increment; -- 查询自增的步长(系统变量)
14.5.3、查询where子条件(Query Where Sub Condition)

其作用为“检索数据中符合条件的值”,其条件由一个或多个表达式组成,结果为布尔值

  • 14.5.3.1、逻辑运算符

    运算符语法描述
    AND &&a AND b a && b逻辑与,两个都为真,结果为真
    OR ||a OR b a || b逻辑或,其中一个为真,结果为真
    NOT !NOT a NOT a=b ! a a!=b逻辑非,真为假,假为真
    -- 1、逻辑运算符
    -- 查询年级id在1~3之间的学生姓名
    SELECT `name`,`gradeid` FROM `student` WHERE `gradeid`>=1 AND `gradeid`<=3;
    SELECT `name`,`gradeid` FROM `student` WHERE `gradeid`>=1 && `gradeid`<=3;
    -- 查询年级id为1或id为5的学生姓名
    SELECT `name`,`gradeid` FROM `student` WHERE `gradeid`=1 OR `gradeid`=5;
    SELECT `name`,`gradeid` FROM `student` WHERE `gradeid`=1 || `gradeid`=5;
    -- 查询年级id不为1的学生姓名
    SELECT `name`,`gradeid` FROM `student` WHERE NOT `gradeid`=1;
    SELECT `name`,`gradeid` FROM `student` WHERE `gradeid`!=1;
    
  • 14.5.3.2、比较运算符

    运算符语法描述
    IS NULLa IS NULL若操作符为NULL,则结果为真
    IS NOT NULLa IS NOT NULL若操作符不为NULL,则结果为真
    BETWEEN ANDa BETWEEN b AND c若a在b和c之间,则结果为真
    LIKEa LIKE b若a模糊匹配b,则结果为真
    INa IN (a1,a2,…)若a等于a1或a2或…中的任意一个值,则结果为真
    -- 查询没有出生日期的学生姓名
    SELECT `birthday`,`name` FROM `student` WHERE `birthday` IS NULL;
    -- 查询有出生日期的学生姓名
    SELECT `birthday`,`name` FROM `student` WHERE `birthday` IS NOT NULL;
    -- 查询年级id在1~4之间的学生姓名
    SELECT `gradeid`,`name` FROM `student` WHERE `gradeid` BETWEEN 1 AND 4;
    -- 查找姓李的学生姓名:其中%代表可以通配0~任意个字符
    SELECT `name` FROM `student` WHERE `name` LIKE '李%';
    -- 查找姓李且名字后面只有一个字的学生姓名:其中_代表可以通配1个字符
    SELECT `name` FROM `student` WHERE `name` LIKE '李_';
    -- 查找姓名中带风字的学生姓名
    SELECT `name` FROM `student` WHERE `name` LIKE '%风%';
    -- 查询学生id为1、2、3的学生姓名
    SELECT `id`,`name` FROM `student` WHERE `id` IN (1,2,3);
    
14.5.4、联表查询(Join Table Query)
8种联表操作描述
内联接(INNER JOIN)若左右两张表中至少有一个匹配,则返回匹配行
左联接(LEFT JOIN) / 左外联接(LEFT OUTER JOIN)左联接与左外联接一致,会从左表中返回所有行,即使右表中没有匹配
右联接(RIGHT JOIN) / 右外联接(RIGHT OUTER JOIN)右联接与右外联接一致,会从右表中返回所有行,即使左表中没有匹配
交叉联接(CROSS JOIN)交叉联接是没有联接条件的联接。一个表的每一行与另一表的每一行合并。这种类型的结果集称为笛卡尔乘积或叉积。
-- 联表查询
-- 1、内联接(INNER JOIN):若左右两张表中至少有一个匹配,则返回匹配行。
-- 使用“内联接”从年级表与学生表中查询所有年级id、年级名称、学生id、学生姓名
SELECT a.`gradeid`,a.`gradename`,b.`id`,b.`name` FROM `grade` AS a
INNER JOIN `student` AS b ON(a.`gradeid`=b.`gradeid`);
-- 2、左联接(LEFT JOIN):会从左表中返回所有行,即使右表中没有匹配
-- 使用“左联接”从年级表与学生表中查询所有年级id、年级名称、学生id、学生姓名
SELECT a.`gradeid`,a.`gradename`,b.`id`,b.`name` FROM `grade` AS a
LEFT JOIN `student` AS b ON(a.`gradeid`=b.`gradeid`);
-- 3、左外联接(LEFT OUTER JOIN):与左联接一致,会从左表中返回所有行,即使右表中没有匹配
-- 使用“左外联接”从年级表与学生表中查询所有年级id、年级名称、学生id、学生姓名
SELECT a.`gradeid`,a.`gradename`,b.`id`,b.`name` FROM `grade` AS a
LEFT OUTER JOIN `student` AS b ON(a.`gradeid`=b.`gradeid`);
-- 4、右联接(RIGHT JOIN):会从右表中返回所有行,即使左表中没有匹配
-- 使用“右联接”从年级表与学生表中查询所有年级id、年级名称、学生id、学生姓名
SELECT a.`gradeid`,a.`gradename`,b.`id`,b.`name` FROM `grade` AS a
RIGHT JOIN `student` AS b ON(a.`gradeid`=b.`gradeid`);
-- 5、右外联接(RIGHT OUTER JOIN):与右联接一致,会从右表中返回所有行,即使左表中没有匹配
-- 使用“右外联接”从年级表与学生表中查询所有年级id、年级名称、学生id、学生姓名
SELECT a.`gradeid`,a.`gradename`,b.`id`,b.`name` FROM `grade` AS a
RIGHT OUTER JOIN `student` AS b ON(a.`gradeid`=b.`gradeid`);
-- 6、完全联接(FULL JOIN):MySQL不支持,返回左表与右表的所有行
-- 7、完全外联接(FULL OUTER JOIN):MySQL不支持,与完全联接一致,返回左表与右表的所有行
-- 8、交叉联接(CROSS JOIN):交叉联接是没有联接条件的联接。一个表的每一行与另一表的每一行合并。这种类型的结果集称为笛卡尔乘积或叉积。
SELECT * FROM `grade` AS a CROSS JOIN `student` AS b;
14.5.5、自连接查询(Self Join Query)

自己的表和自己的表连接,即,将一张表拆分成两张一样的父子类表即可

  • 父类表

    idname
    1软件开发
    2JavaSE
    3HTML5
    4CSS3
    5JavaScript
    6MySQL
    7JavaWeb
    8SSM框架
    9大前端进阶
    10微服务开发
    11Linux运维
    12常用中间件
  • 子类表

    sub_ididname
    11软件开发
    12JavaSE
    23HTML5
    34CSS3
    35JavaScript
    46MySQL
    57JavaWeb
    68SSM框架
    79大前端进阶
    810微服务开发
    911Linux运维
    1012常用中间件
-- 自连接查询:即,自己的表和自己的表连接,亦即,将一张表拆分成两张一样的父子类表即可
SELECT a.`name` AS '父类列名',b.`name` AS '子类列名'
FROM `selftable` AS a,`selftable` AS b
WHERE a.`id`=b.`sub_id`;
14.5.6、分页和排序查询(Pages And Sorts Query)
/*
分页和排序查询
1、分页语法:LIMIT 查询页起始下标,页面大小(如:LIMIT 0,10)。
1.1、第1页:LIMIT 0,num     =>   (1-1)*num,num,
1.2、第2页:LIMIT 1*num,num   =>   (2-1)*num,num,
1.3、第3页:LIMIT 2*num,num   =>   (3-1)*num,num,
...
1.n、第n页:LIMIT (n-1)*num,num   =>   (n-1)*num,num,
推导出分页公式:(n-1)*num,num;且其中num代表页面大小,n代表总页数(总页数=数据总数量/页面大小),(n-1)*num代表查询页起始下标;
2、排序语法:ORDER BY 字段列1,字段列2,... ASC(升序)/DESC(升序)。
*/
-- 查询1~5年级id中学生分数排名前3且学生分数大于等于80分的学生信息(年级id、学生id、学生姓名、学生性别、学生分数)
SELECT `gradeid` 年级id,`id` 学生id,`name` 学生姓名,`sex` 学生性别,`score` 学生分数 FROM `student`
WHERE `gradeid` BETWEEN 1 AND 5 AND `score`>=80
ORDER BY `score` DESC
LIMIT 0,3;
14.5.7、子查询和嵌套查询(Sub Query And Nested Query)

子查询和嵌套查询的本质:“在查询where语句中嵌套一个子查询语句”

-- 子查询和嵌套查询
-- 查询1~5年级id中所有学生信息(年级id、学生id、学生姓名、学生性别、学生分数)
select `gradeid` as 年级id,`id` as 学生id,`name` as 学生姓名,`sex` as 学生性别,`score` as 学生分数 from `student`
where `gradeid` in (select `gradeid` from `grade` where `gradeid` in (1,2,3,4,5));
14.5.8、分组和过滤查询(Group And Filter Query)
-- 分组和过滤查询
-- 查询所有学生中不同年级id的最高分、最低分、平均分,且平均数大于等于80分的年级名称
SELECT `gradename` 年级名称,MAX(`score`) 最高分,MIN(`score`) 最低分,AVG(`score`) 平均分
FROM `student` s INNER JOIN `grade` g ON(s.`gradeid`=g.`gradeid`)
GROUP BY s.`gradeid` /*按照字段“gradeid”分组数据*/
HAVING 平均分>=80; /*按照新字段“平均分”过滤数据*/

15、MySQL函数(MySQL Function)

15.1、常规函数(General Function)

-- 常规函数
-- 1、数学函数
SELECT ABS(-1); -- 绝对值
SELECT CEILING(5.4);-- 向上取整
SELECT FLOOR(5.4);-- 向下取整
SELECT RAND();-- 返回一个0~1之间的随机浮点数
SELECT SIGN(0);-- 判断一个数的符号:为0时返回0,为正数时返回1,为负数时返回-1
-- 2、字符串函数
SELECT CHAR_LENGTH('mysql');-- 字符串长度
SELECT CONCAT('喜','欢','你');-- 拼接字符串
SELECT INSERT('喜欢你',1,3,'我爱你');-- 指定字符串替换掉从指定位置指定长度的字符串
SELECT UPPER('MySQL');-- 大写字母
SELECT LOWER('MySQL');-- 小写字母
SELECT INSTR('MySQL MySQL','y');-- 返回字符串中第1次出现子字符串的位置
SELECT REPLACE('MySQL MySQL','MySQL','mysql');-- 替换字符串中出现的所有指定字符串
SELECT SUBSTR('hijklMySQLmnopq',6,5);-- 返回指定位置指定长度的子字符串
SELECT REVERSE('MySQL');-- 反转字符串
-- 3、日期时间函数
SELECT CURRENT_DATE();-- 获取当前日期
SELECT CURDATE();-- 获取当前日期
SELECT NOW();-- 获取当前日期时间
SELECT LOCALTIME();-- 获取本地日期时间
SELECT SYSDATE();-- 获取当前系统日期时间
SELECT YEAR(NOW());-- 获取当前年份
SELECT MONTH(NOW());-- 获取当前月份
SELECT DAY(NOW());-- 获取当前日
SELECT HOUR(NOW());-- 获取当前小时
SELECT MINUTE(NOW());-- 获取当前分钟
SELECT SECOND(NOW());-- 获取当前秒
-- 4、系统参数函数
SELECT SYSTEM_USER();-- 获取系统用户
SELECT USER();-- 获取当前用户
SELECT VERSION();-- 获取系统版本

15.2、聚合函数(Aggregate Function)

-- 聚合函数
SELECT COUNT(`score`) FROM `student`;-- 计数,会忽略所有的null值
SELECT COUNT(*) FROM `student`;-- 计数,不会忽略所有的null值,其本质:计算行数
SELECT COUNT(1) FROM `student`;-- 计数,不会忽略所有的null值,其本质:计算行数
SELECT SUM(`score`) '总和' FROM `student`;-- 求和
SELECT AVG(`score`) '平均分' FROM `student`;-- 求平均值
SELECT MAX(`score`) '最高分' FROM `student`;-- 求最大值
SELECT MIN(`score`) '最低分' FROM `student`;-- 求最小值

15.3、数据库MD5加密函数(DataBase MD5 Encryption Function)

MD5信息摘要算法(MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致

-- MD5加密函数:主要是增强算法的复杂度和不可逆性,其返回值为32位十六进制数字的字符串形式。
-- 创建MD5测试表
CREATE TABLE `md5_table`(
`id` INT(10) NOT NULL AUTO_INCREMENT COMMENT '唯一标识',
`name` VARCHAR(10) NOT NULL COMMENT '用户名',
`pwd` VARCHAR(20) NOT NULL COMMENT '密码',
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
-- 插入明文密码的数据
INSERT INTO `md5_table`(`name`,`pwd`) VALUES('张三','123'),('李四','456');
-- 插入非明文密码(MD5加密)的数据
INSERT INTO `md5_table`(`name`,`pwd`) VALUES('赵五',MD5('123456')),('钱六',MD5('123321'));
-- 密码校验:将用户传递的密码进行MD5加密,然后比对加密后的值
SELECT * FROM `md5_table` WHERE `name`='赵五' AND `pwd`=MD5('123456');
SELECT * FROM `md5_table` WHERE `name`='钱六' AND `pwd`=MD5('123321');

16、MySQL事务(MySQL Transaction)

事务一般是将一组SQL放到一个批次中去执行(要么都成功,要么都失败),且一个事务对应一个完整的业务(如:银行账户转账业务),事务有四个基本要素,即,ACID原则,如下所示

16.1、原子性(Atomicity)

或称不可分割性,原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生

16.2、一致性(Consistency)

一致性是指事务前后数据的完整性必须保持一致

16.3、隔离性(Isolation)

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

  • 16.3.1、隔离性可以解决的问题(Isolation Can Solve The Problem)

    • 16.3.1.1、脏读

      指一个事务读取了另外一个事务未提交的数据

    • 16.3.1.2、不可重复读

      在一个事务内读取表中的某一行数据,多次读取结果不同(这个不一定是错误,只是某些场合不对)

    • 16.3.1.3、虚度(幻读)

      是指在一个事务内读取到了别的事务插入的数据,导致前后读取数量总量不一致

  • 16.3.2、四种隔离级别设置(Four Isolation Level Settings)

    -- 设置与查询事务隔离级别
    -- 设置事务隔离级别为“串行化”:可避免脏读、不可重复读、虚读情况的发生。
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    -- 设置事务隔离级别为“可重复读”:可避免脏读、不可重复读情况的发生。
    SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    -- 设置事务隔离级别为“读已提交”:可避免脏读情况发生。
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
    -- 设置事务隔离级别为“读未提交”:最低级别,以上情况均无法保证。
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    -- 查询当前事务隔离级别
    SELECT @@tx_isolation;
    

16.4、持久性(Durability)

持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

-- MySQL事务
SET autocommit=1;-- 开启事务自动提交(MySQL默认情形)
-- 手动处理业务
SET autocommit=0;-- 关闭事务自动提交
-- 开启事务:标记一个事务的开始,从这个之后的SQL都在同一个事务内
START TRANSACTION 事务名;
/*
执行SQL语句块:
SQL语句1;
SQL语句2;
......
SQL语句n;
*/
-- 若SQL语句执行成功,则提交事务
COMMIT 事务名;
-- 若SQL语句执行失败,则回滚事务
ROLLBACK 事务名;
-- 结束事务
SET autocommit=1;-- 开启事务自动提交
-- 设置事务保存点
SAVEPOINT 事务保存点名;
-- 回滚到事务保存点
ROLLBACK TO SAVEPOINT 事务保存点名;
-- 撤销事务保存点
RELEASE SAVEPOINT 事务保存点名;

17、MySQL索引(MySQL Index)

索引的本质是数据结构,其可以使MySQL高效获取数据的数据结构

17.1、索引分类(Index Classification)

  • 17.1.1、主键索引

PRIMARY KEY关键字,唯一的标识,主键不可重复,只能有一个列作为主键

  • 17.1.2、唯一索引

UNIQUE KEY关键字,避免重复的列出现,唯一索引可以重复,多个列都可以标识为唯一索引

  • 17.1.3、常规索引

KEY或INDEX关键字

  • 17.1.4、全文索引

    FULLTEXT关键字,只能为CHAR、VARCHAR、TEXT列创建,可以快速定位数据

    • 17.1.4.1、MySQL5.6版本之前,只有 MyISAM数据库引擎支持全文索引
    • 17.1.4.2、MySQL5.6版本之后,InnoDB或MyISAM数据库引擎都支持全文索引

17.2、索引使用(Index Use)

-- MySQL索引
/*
索引的使用:索引在数据量小时,效率不明显,在数据量大时,效率非常明显。
1、在创建表的时候给字段添加索引
2、在创建表完后再给字段添加索引
*/
-- 显示指定表所有的索引信息
SHOW INDEX FROM `selftable`;
-- 增加一个全文索引
ALTER TABLE `selftable` ADD FULLTEXT INDEX `name`(`name`);
-- 分析SQL语句执行状况
EXPLAIN SELECT * FROM `selftable`-- 非全文索引
EXPLAIN SELECT * FROM `selftable` WHERE MATCH(`name`) AGAINST('Java');-- 全文索引

17.3、索引原则(Index Principle)

  • 17.3.1、表中索引并非越多越好
  • 17.3.2、不要对表中易变动数据字段列加索引
  • 17.3.3、数据量较小的表中不需要加索引
  • 17.3.4、表中索引一般加在经常查询的字段上

18、权限管理和数据备份(Rights Management And Data Backup)

18.1、权限管理(Rights Management)

18.1.1、SQLyog可视化管理操作

MySQL权限管理参考网址

18.1.2、SQL命令语句操作
-- 用户权限管理
-- 创建用户
CREATE USER `xueshanxuehai` IDENTIFIED BY '123456';
-- 修改当前用户秘密
SET PASSWORD=PASSWORD('123456');
-- 修改指定用户密码
SET PASSWORD FOR `xueshanxuehai`=PASSWORD('123');
-- 重命名用户名称
RENAME USER `xueshanxuehai` TO `xsxh`;
-- 用户授权:其中参数“ALL PRIVILEGES”代表除了给别人授权之外的所有权限
GRANT ALL PRIVILEGES ON *.* TO `xsxh`;
-- 查询指定用户权限
SHOW GRANTS FOR `xsxh`;
SHOW GRANTS FOR root@localhost;
-- 撤销权限
REVOKE ALL PRIVILEGES ON *.* FROM `xsxh`;
-- 删除用户
DROP USER `xsxh`;

18.2、数据备份(Data Backup)

18.2.1、SQLyog可视化管理操作

MySQL数据备份参考网址

18.2.2、CMD命令语句操作
# 导出备份数据
# 导出单张数据表备份数据:mysqldump -h主机名 -u用户名 -p密码 库名 表名 > 物理磁盘位置路径/文件名.sql
mysqldump -hlocalhost -uroot -p123456 school student > D:/a.sql
# 导出多张数据表备份数据:mysqldump -h主机名 -u用户名 -p密码 库名 表1名 表2名 ... > 物理磁盘位置路径/文件名.sql
mysqldump -hlocalhost -uroot -p123456 school student grade md5_table > D:/b.sql
# 导出数据库备份数据:mysqldump -h主机名 -u用户名 -p密码 库名 > 物理磁盘位置路径/文件名.sql
mysqldump -hlocalhost -uroot -p123456 school > D:/c.sql
# 导入备份数据
# 若导入备份数据对应的数据库不存在,则需先创建指定空数据库
# 登录MySQL
mysql -uroot -p123456
# 创建指定空数据库
create database `school`;
# 导入指定数据库数据表备份数据(方式1)
# 登录MySQL
mysql -uroot -p123456
# 切换到指定数据库
use `school`;
# 导入指定数据表备份数据
source D:/c.sql
# 导入指定数据库数据表备份数据(方式2)
mysql -hlocalhost -uroot -p123456 school < D:/c.sql
# 特别注意:1、为防止数据丢失,需备份数据库数据;2、若需把数据给他人测试,直接给备份sql文件即可。

19、规范数据库设计(Standardize DataBase Design)

19.1、不同数据库设计(Different DataBase Design)

  • 19.1.1、不好的数据库设计

    • 19.1.1.1、数据冗余、浪费空间
    • 19.1.1.2、数据库插入和删除都不方便(会出现外键约束异常)
    • 19.1.1.3、程序性能差
  • 19.1.2、良好的数据库设计

    • 19.1.2.1、节省内存空间
    • 19.1.2.2、保证数据库的完整性
    • 19.1.2.3、便于系统开发

19.2、三大范式(Three Paradigms)

  • 19.2.1、第一范式(First Paradigm)

保证每一列不可再分(即,原子性)

  • 19.2.2、第二范式(Second Paradigm)

在满足第一范式的前提下,保证每张表只描述一件事情

  • 19.2.3、第三范式(Third Paradigm)

    在满足第一和第二范式的前提下,保证数据表中每一列数据都和主键直接相关,而不能间接相关

19.3、规范性与性能的问题(Normative And Performance)

  • 19.3.1、关联查询的表不得超过三张表
  • 19.3.2、考虑商业化的需求与目标(成本与用户体验)时,数据库的性能更重要
  • 19.3.3、在考虑性能时,也需适当的考虑一下规范性
  • 19.3.4、有时会给某些表故意增加一些冗余的字段,从而提升性能(如:可以从多表查询变为单表查询)
  • 19.3.5、有时也会给某些表增加一些计算列,从而提升性能(如:增加索引列,可以将大数据量查询变为小数据量的查询,从而提高查询速度)

20、JDBC(Java DataBase Connectivity)

SUN公司为了简化开发人员对数据库的统一操作,提供了一个Java操作数据库的规范(即,JDBC),且这些规范的实现都由具体的数据库厂商去做,从而开发人员只需掌握JDBC接口的操作即可,如下图所示

JDBC连接数据库示意图

20.1、使用IDEA编写JDBC程序(Use IDEA Write JDBC Program)

其具体实现步骤,如下所示

  • 20.1.1、创建一个IDEA工程项目

  • 20.1.2、导入数据库驱动文件(即,mysql-connector-java-5.1.47.jar),如下图所示

    导入数据库驱动文件

  • 20.1.3、将数据库驱动文件(即,mysql-connector-java-5.1.47.jar)添加为库,如下图所示

    添加数据库驱动文件为库

  • 20.1.4、编写JDBC程序,如下所示

    其示例代码,如下所示

    import java.sql.*;
    public class JDBC {
        public static void main(String[] args) throws ClassNotFoundException, SQLException {
            //1、加载JDBC驱动(固定写法)
            Class.forName("com.mysql.jdbc.Driver");
            //2、URL:其格式为“jdbc:协议(如mysql)://主机地址:端口号/数据库名?参数1(是否使用Unicode字符集)&参数2(指定字符编码)&参数3(是否使用SSL连接)”。
            //特别注意:把url后边的安全连接参数删除(有警告)或改成false[SQL版本大于connect版本,就要设置成false])。
            //String url="jdbc:mysql://localhost:3306/jdbc_test?useUnicode=true&characterEncoding=utf8&useSSL=true";
            String url="jdbc:mysql://localhost:3306/jdbc_test?useUnicode=true&characterEncoding=utf8&useSSL=false";
            //3、用户信息
            String username="root";//用户名
            String password="123456";//密码
            //4、数据库连接对象
            Connection connection= DriverManager.getConnection(url,username,password);
            //5、SQL语句执行对象
            Statement statement=connection.createStatement();
            //6、SQL语句
            String sql="select * from grade";
            //7、执行SQL语句
            ResultSet resultSet=statement.executeQuery(sql);//返回查询结果集(其中包含全部查询结果)
            while(resultSet.next()){
                System.out.println("gradeid="+resultSet.getObject("gradeid"));
                System.out.println("gradename="+resultSet.getObject("gradename"));
            }
            //8、释放数据库连接对象资源
            resultSet.close();
            statement.close();
            connection.close();
        }
    }
    

    其运行结果,如下所示

    gradeid=1
    gradename=1年级
    gradeid=2
    gradename=2年级
    gradeid=3
    gradename=3年级
    gradeid=5
    gradename=4年级
    gradeid=6
    gradename=5年级
    

20.2、JDBC对象(JDBC Objects)

20.2.1、Connection对象(Connection Object)
//数据库连接对象
Connection connection= DriverManager.getConnection(url,username,password);
connection.commit();//数据库事务提交
connection.rollback();//数据库事务回滚
connection.setAutoCommit(true);//设置数据库事务是否自动提交,默认参数为true,代表自动提交;否则参数为false,代表不自动提交
20.2.2、ResultSet对象(ResultSet Object)
ResultSet resultSet=statement.executeQuery(sql);//返回查询结果集(其中包含全部查询结果)
resultSet.getObject("gradeid");//不知道"gradeid"列类型
resultSet.getInt("gradeid");//知道"gradeid"列类型为Int
resultSet.beforeFirst();//移动到第一行数据
resultSet.afterLast();//移动到最后行数据
resultSet.next();//移动到下一行数据
resultSet.previous();//移动到上一行数据
resultSet.absolute(1);//移动到指定行数据
20.2.3、Statement对象(Statement Object)

JDBC中Statement对象用于向数据库发送SQL语句(增查删改操作,即 CRUD操作)

其中Statement对象的executeUpdate方法,用于向数据库发送增、删、改操作的SQL语句,且执行完后,会返回一个整数(代表对应数据表受影响的行数)

其中Statement对象的executeQuery方法,用于向数据库发送查操作的SQL语句,且执行完后,会返回一个ResultSet对象(代表对应数据表查询的结果)

20.2.3.1、提取工具类

配置文件(db.properties)内容,如下所示

# 数据库驱动名称
driver=com.mysql.jdbc.Driver
# url,其中特别注意的是:当数据库安装版本低于数据库驱动版本时“useSSL参数设定值”必须为"useSSL=true",否则必须为"useSSL=false"。
url=jdbc:mysql://localhost:3306/jdbc_test?useUnicode=true&characterEncoding=utf8&useSSL=false
# 用户名
username=root
# 密码
password=123456

JDBCUtils_STA工具类示例代码,如下所示

package jdbc.utils;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils_STA {
    private static String driver=null;
    private static String url=null;
    private static String username=null;
    private static String password=null;
    //静态代码快(只会在第一次加载类时执行)
    static{
        try {
            InputStream inputStream= JDBCUtils_STA.class.getClassLoader().getResourceAsStream("resources/db.properties");
            Properties properties=new Properties();
            properties.load(inputStream);
            driver=properties.getProperty("driver");
            url=properties.getProperty("url");
            username=properties.getProperty("username");
            password=properties.getProperty("password");
            Class.forName(driver);//固定写法,加载数据库驱动
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取数据库连接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,username,password);
    }
    //释放数据库连接对象资源
    public static void release(Connection conn, Statement sta, ResultSet res){
        if(res!=null){
            try {
                res.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(sta!=null){
            try {
                sta.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}
20.2.3.2、实现增查删改操作
  • 20.2.3.2.1、增操作(Create操作)

    其示例代码,如下所示

    package jdbc.statement;
    import jdbc.utils.JDBCUtils_STA;
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    //SQL语句增加操作
    public class InsertSql {
        public static void main(String[] args) {
            Connection conn=null;
            Statement sta=null;
            ResultSet res=null;
            try {
                conn= JDBCUtils_STA.getConnection();//获取数据库连接对象
                sta=conn.createStatement();//获得SQL语句指定对象
                String sql="insert into grade(gradeid,gradename) VALUES(7,'7年级')";//SQL语句字符串
                int rn=sta.executeUpdate(sql);
                if(rn>0){
                    System.out.println("插入数据成功");
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_STA.release(conn,sta,res);
            }
        }
    }
    

    其运行结果,如下所示

    插入数据成功
    
  • 20.2.3.2.2、删操作(Delete操作)

    其示例代码,如下所示

    package jdbc.statement;
    import jdbc.utils.JDBCUtils_STA;
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    //SQL语句删除操作
    public class DeleteSql {
        public static void main(String[] args) {
            Connection conn=null;
            Statement sta=null;
            ResultSet res=null;
            try {
                conn= JDBCUtils_STA.getConnection();//获取数据库连接对象
                sta=conn.createStatement();//获得SQL语句指定对象
                String sql="delete from grade where gradename='8年级'";//SQL语句字符串
                int rn=sta.executeUpdate(sql);
                if(rn>0){
                    System.out.println("删除数据成功");
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_STA.release(conn,sta,res);
            }
        }
    }
    

    其运行结果,如下所示

    删除数据成功
    
  • 20.2.3.2.3、改操作(Update操作)

    其示例代码,如下所示

    package jdbc.statement;
    import jdbc.utils.JDBCUtils_STA;
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    //SQL语句修改操作
    public class UpdateSQL {
        public static void main(String[] args) {
            Connection conn=null;
            Statement sta=null;
            ResultSet res=null;
            try {
                conn= JDBCUtils_STA.getConnection();//获取数据库连接对象
                sta=conn.createStatement();//获得SQL语句指定对象
                String sql="update grade set gradename='8年级' where gradename='7年级'";//SQL语句字符串
                int rn=sta.executeUpdate(sql);
                if(rn>0){
                    System.out.println("更新数据成功");
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_STA.release(conn,sta,res);
            }
        }
    }
    

    其运行结果,如下所示

    更新数据成功
    
  • 20.2.3.2.4、查操作(Retrieve操作)

    其示例代码,如下所示

    package jdbc.statement;
    import jdbc.utils.JDBCUtils_STA;
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    //SQL语句查询操作
    public class SelectSql {
        public static void main(String[] args) {
            Connection conn=null;
            Statement sta=null;
            ResultSet res=null;
            try {
                conn= JDBCUtils_STA.getConnection();//获取数据库连接对象
                sta=conn.createStatement();//获得SQL语句指定对象
                String sql="select * from grade";//SQL语句字符串
                res=sta.executeQuery(sql);
                while(res.next()){
                    System.out.println("gradeid="+res.getInt("gradeid"));
                    System.out.println("gradename="+res.getString("gradename"));
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_STA.release(conn,sta,res);
            }
        }
    }
    

    其运行结果,如下所示

    gradeid=1
    gradename=1年级
    gradeid=2
    gradename=2年级
    gradeid=3
    gradename=3年级
    gradeid=4
    gradename=4年级
    gradeid=5
    gradename=5年级
    gradeid=6
    gradename=6年级
    
  • 20.2.3.2.5、会发生SQL注入问题

    其示例代码,如下所示

    package jdbc.statement;
    import jdbc.utils.JDBCUtils_STA;
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    /**
     * SQL注入问题:由于SQL会被拼接,从而存在漏洞,会容易被攻击导致数据泄露。
     */
    public class SqlInjectionProblem {
        public static void main(String[] args) {
            //login("张三","12321");//正常获取用户信息
            login(" 'or '1=1"," 'or '1=1");//异常获取所有用户信息(即,SQL注入问题)
        }
        //登录业务
        public static void login(String username,String password){
            Connection conn=null;
            Statement sta=null;
            ResultSet res=null;
            try {
                conn= JDBCUtils_STA.getConnection();//获取数据库连接对象
                sta=conn.createStatement();//获得SQL语句指定对象
                String sql="select * from student where name='"+username+"' and pwd='"+password+"'";//SQL语句字符串
                res=sta.executeQuery(sql);
                while(res.next()){
                    System.out.println("name="+res.getString("name"));
                    System.out.println("pwd="+res.getString("pwd"));
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_STA.release(conn,sta,res);
            }
        }
    }
    

    其运行结果,如下所示

    name=刘大
    pwd=12321
    name=王二
    pwd=12321
    name=张三
    pwd=12321
    name=李四
    pwd=12321
    name=赵五
    pwd=12321
    name=张风雷
    pwd=12321
    name=李风雨
    pwd=12321
    
20.2.4、PreparedStatement对象(PreparedStatement Object)

PreparedStatement可以防止Statement导致的SQL注入问题发生,且执行效率更好

20.2.4.1、提取工具类

配置文件(db.properties)内容,如下所示

# 数据库驱动名称
driver=com.mysql.jdbc.Driver
# url,其中特别注意的是:当数据库安装版本低于数据库驱动版本时“useSSL参数设定值”必须为"useSSL=true",否则必须为"useSSL=false"。
url=jdbc:mysql://localhost:3306/jdbc_test?useUnicode=true&characterEncoding=utf8&useSSL=false
# 用户名
username=root
# 密码
password=123456

JDBCUtils_PSTA工具类示例代码,如下所示

package jdbc.utils;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils_PSTA {
    private static String driver=null;
    private static String url=null;
    private static String username=null;
    private static String password=null;
    //静态代码快(只会在第一次加载类时执行)
    static{
        try {
            InputStream inputStream= JDBCUtils_PSTA.class.getClassLoader().getResourceAsStream("resources/db.properties");
            Properties properties=new Properties();
            properties.load(inputStream);
            driver=properties.getProperty("driver");
            url=properties.getProperty("url");
            username=properties.getProperty("username");
            password=properties.getProperty("password");
            Class.forName(driver);//固定写法,加载数据库驱动
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取数据库连接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,username,password);
    }
    //释放数据库连接对象资源
    public static void release(Connection conn, PreparedStatement psta, ResultSet res){
        if(res!=null){
            try {
                res.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(psta!=null){
            try {
                psta.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}
20.2.4.2、实现增查删改操作
  • 20.2.4.2.1、增操作(Create操作)

    其示例代码,如下所示

    package jdbc.preparedstatement;
    import jdbc.utils.JDBCUtils_PSTA;
    import java.sql.*;
    //SQL语句增加操作
    public class InsertSql {
        public static void main(String[] args) {
            Connection conn=null;
            PreparedStatement psta=null;
            ResultSet res=null;
            try {
                //获取数据库连接对象
                conn= JDBCUtils_PSTA.getConnection();
                //SQL语句字符串:使用占位符(?)代替参数
                String sql="insert into student(name,pwd,sex,birthday,gradeid) values(?,?,?,?,?)";
                //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
                psta= conn.prepareStatement(sql);
                //手动给参数赋值,按照字段列的顺序一一对应
                psta.setString(1,"学山");
                psta.setString(2,"123456789");
                psta.setString(3,"男");
                /**
                 * 特别注意:
                 * 1、Java日期时间:java.util.Date(),Java时间戳:java.util.Date().getTime();
                 * 2、数据库日期时间:java.sql.Date();数据库时间戳:java.sql.Date().getTime();
                 */
                psta.setDate(4,new java.sql.Date(new java.util.Date().getTime()));
                psta.setInt(5,1);
                int rn=psta.executeUpdate();//执行SQL语句
                if(rn>0){
                    System.out.println("插入数据成功");
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_PSTA.release(conn,psta,res);
            }
        }
    }
    

    其运行结果,如下所示

    插入数据成功
    
  • 20.2.4.2.2、删操作(Delete操作)

    其示例代码,如下所示

    package jdbc.preparedstatement;
    import jdbc.utils.JDBCUtils_PSTA;
    import java.sql.*;
    //SQL语句删除操作
    public class DeleteSql {
        public static void main(String[] args) {
            Connection conn=null;
            PreparedStatement psta=null;
            ResultSet res=null;
            try {
                //获取数据库连接对象
                conn= JDBCUtils_PSTA.getConnection();
                //SQL语句字符串:使用占位符(?)代替参数
                String sql="delete from student where name=?";
                //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
                psta= conn.prepareStatement(sql);
                //手动给参数赋值,按照字段列的顺序一一对应
                psta.setString(1,"学海");
                int rn=psta.executeUpdate();//执行SQL语句
                if(rn>0){
                    System.out.println("删除数据成功");
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_PSTA.release(conn,psta,res);
            }
        }
    }
    

    其运行结果,如下所示

    删除数据成功
    
  • 20.2.4.2.3、改操作(Update操作)

    其示例代码,如下所示

    package jdbc.preparedstatement;
    import jdbc.utils.JDBCUtils_PSTA;
    import java.sql.*;
    //SQL语句修改操作
    public class UpdateSQL {
        public static void main(String[] args) {
            Connection conn=null;
            PreparedStatement psta=null;
            ResultSet res=null;
            try {
                //获取数据库连接对象
                conn= JDBCUtils_PSTA.getConnection();
                //SQL语句字符串:使用占位符(?)代替参数
                String sql="update student set name=? where name=?";
                //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
                psta= conn.prepareStatement(sql);
                //手动给参数赋值,按照字段列的顺序一一对应
                psta.setString(1,"学海");
                psta.setString(2,"学山");
                int rn=psta.executeUpdate();//执行SQL语句
                if(rn>0){
                    System.out.println("更新数据成功");
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_PSTA.release(conn,psta,res);
            }
        }
    }
    

    其运行结果,如下所示

    更新数据成功
    
  • 20.2.4.2.4、查操作(Retrieve操作)

    其示例代码,如下所示

    package jdbc.preparedstatement;
    import jdbc.utils.JDBCUtils_PSTA;
    import java.sql.*;
    //SQL语句查询操作
    public class SelectSql {
        public static void main(String[] args) {
            Connection conn=null;
            PreparedStatement psta=null;
            ResultSet res=null;
            try {
                //获取数据库连接对象
                conn= JDBCUtils_PSTA.getConnection();
                //SQL语句字符串:使用占位符(?)代替参数
                String sql="select name,pwd,sex,birthday,gradeid from student where name=?";
                //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
                psta= conn.prepareStatement(sql);
                //手动给参数赋值,按照字段列的顺序一一对应
                psta.setString(1,"张三");
                res=psta.executeQuery();//执行SQL语句
                while(res.next()){
                    System.out.println("name="+res.getString("name"));
                    System.out.println("pwd="+res.getString("pwd"));
                    System.out.println("sex="+res.getString("sex"));
                    System.out.println("birthday="+res.getDate("birthday"));
                    System.out.println("gradeid="+res.getInt("gradeid"));
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_PSTA.release(conn,psta,res);
            }
        }
    }
    

    其运行结果,如下所示

    name=张三
    pwd=12321
    sex=男
    birthday=2021-10-03
    gradeid=3
    
  • 20.2.4.2.5、不会发生SQL注入问题

    其示例代码,如下所示

    package jdbc.preparedstatement;
    import jdbc.utils.JDBCUtils_PSTA;
    import java.sql.*;
    /**
     * SQL注入问题:由于SQL会被拼接,从而存在漏洞,会容易被攻击导致数据泄露。
     */
    public class SqlInjectionProblem {
        public static void main(String[] args) {
            //login("张三","12321");//正常获取用户信息
            login(" 'or '1=1"," 'or '1=1");//不能获取用户信息(即,不会发生SQL注入问题)
        }
        //登录业务
        public static void login(String username,String password){
            Connection conn=null;
            PreparedStatement psta=null;
            ResultSet res=null;
            try {
                //获取数据库连接对象
                conn= JDBCUtils_PSTA.getConnection();
                //SQL语句字符串:使用占位符(?)代替参数
                String sql="select name,pwd,sex,birthday,gradeid from student where name=? and pwd=?";
                //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
                psta= conn.prepareStatement(sql);
                //手动给参数赋值,按照字段列的顺序一一对应
                psta.setString(1,username);
                psta.setString(2,password);
                res=psta.executeQuery();//执行SQL语句
                while(res.next()){
                    System.out.println("name="+res.getString("name"));
                    System.out.println("pwd="+res.getString("pwd"));
                    System.out.println("sex="+res.getString("sex"));
                    System.out.println("birthday="+res.getDate("birthday"));
                    System.out.println("gradeid="+res.getInt("gradeid"));
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_PSTA.release(conn,psta,res);
            }
        }
    }
    

20.3、使用IDEA连接数据库(Use IDEA Connection DataBase)

其具体实现步骤,如下所示

  • 20.3.1、选择MySQL连接项目,如下图所示

    选择MySQL连接项目

  • 20.3.2、配置MySQL数据源驱动,如下图所示

    配置MySQL数据源驱动

  • 20.3.3、测试MySQL连接,如下图所示

    测试MySQL连接

  • 20.3.4、选择MySQL数据库"jdbc_test",如下图所示

    选择MySQL数据库"jdbc_test"

  • 20.3.5、MySQL数据库配置完成,如下图所示

    MySQL数据库配置完成

20.4、使用IDEA操作数据库连接池(Use IDEA Operation DataBase Connection Pool)

一般操作数据库时,会频繁的连接、处理、释放,十分消耗资源,所以建议操作数据库连接池(即,采取池化技术<如:预先准备好一些缓存资源,数据库连接时优先使用这些缓存资源,从而避免频繁创建于释放资源>)

数据库连接池的本质就是实现DataSource接口

20.4.1、DBCP数据库连接池

前提条件:先导入对应jar包(即,commons-dbcp-1.4.jar、commons-pool-1.6.jar),具体操作请参考前面“导入数据库驱动文件(即,mysql-connector-java-5.1.47.jar)”操作

20.4.1.1、提取工具类

配置文件(db_dbcp.properties)内容,如下所示

# 连接设置:其中所有的名字都是DBCP数据源(即,DBCP数据库连接池)中定义好的。
# 数据库驱动名称
driverClassName=com.mysql.jdbc.Driver
# url,其中特别注意的是:当数据库安装版本低于数据库驱动版本时“useSSL参数设定值”必须为"useSSL=true",否则必须为"useSSL=false"。
url=jdbc:mysql://localhost:3306/jdbc_test?useUnicode=true&characterEncoding=utf8&useSSL=false
# 用户名
username=root
# 密码
password=123456
# 初始化连接数
initialSize=10
# 最大连接数
maxActive=50
# 最大空闲连接数
maxIdle=20
# 最小空闲连接数
minIdle=5
# 超时等待时间(单位:毫秒)
maxWait=60000
# JDBC驱动建立连接时附带的连接属性:其格式为“属性名=property”
connectionProperties=useUnicode=true;characterEncoding=utf8
# 指定由连接池所创建的连接对象的自动提交(auto-commit)状态
defaultAutoCommit=true
# 指定由连接池所创建的连接对象的只读(read-only)状态:若未设置值,则“setReadOnly”方法不被调用(某些驱动并不支持只读模式,如Informix)
defaultReadOnly=
# 指定由连接池所创建的连接对象的事务隔离级别(TransactionIsolation):NONE、READ_UNCOMMITTED(读未提交)、READ_COMMITTED(读提交)、REPEATABLE_READ(可重复读取)、SERIALIZABLE(可序化)
defaultTransactionIsolation=READ_UNCOMMITTED

JDBCUtils_DBCP工具类示例代码,如下所示

package jdbc.utils;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
public class JDBCUtils_DBCP {
    private static DataSource dataSource = null;
    //静态代码快(只会在第一次加载类时执行)
    static {
        try {
            InputStream inputStream = JDBCUtils_DBCP.class.getClassLoader().getResourceAsStream("resources/db_dbcp.properties");
            Properties properties = new Properties();
            properties.load(inputStream);
            //创建数据源(数据库连接池):固定方式,使用工厂模式创建
            dataSource = BasicDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取数据库连接
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();//从数据源(数据库连接池)中获取连接
    }
    //释放数据库连接对象资源
    public static void release(Connection conn, PreparedStatement psta, ResultSet res) {
        if (res != null) {
            try {
                res.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (psta != null) {
            try {
                psta.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}
20.4.1.2、实现增查删改操作
  • 20.4.1.2.1、增操作(Create操作)

    其示例代码,如下所示

    package jdbc.dbcp;
    import jdbc.utils.JDBCUtils_DBCP;
    import java.sql.*;
    //SQL语句增加操作
    public class InsertSql {
        public static void main(String[] args) {
            Connection conn=null;
            PreparedStatement psta=null;
            ResultSet res=null;
            try {
                //获取数据库连接对象
                conn= JDBCUtils_DBCP.getConnection();
                //SQL语句字符串:使用占位符(?)代替参数
                String sql="insert into student(name,pwd,sex,birthday,gradeid) values(?,?,?,?,?)";
                //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
                psta= conn.prepareStatement(sql);
                //手动给参数赋值,按照字段列的顺序一一对应
                psta.setString(1,"学山");
                psta.setString(2,"123456789");
                psta.setString(3,"男");
                /**
                 * 特别注意:
                 * 1、Java日期时间:java.util.Date(),Java时间戳:java.util.Date().getTime();
                 * 2、数据库日期时间:java.sql.Date();数据库时间戳:java.sql.Date().getTime();
                 */
                psta.setDate(4,new Date(new java.util.Date().getTime()));
                psta.setInt(5,1);
                int rn=psta.executeUpdate();//执行SQL语句
                if(rn>0){
                    System.out.println("插入数据成功");
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_DBCP.release(conn,psta,res);
            }
        }
    }
    

    其运行结果,如下所示

    插入数据成功
    
  • 20.4.1.2.2、删操作(Delete操作)

    其示例代码,如下所示

    package jdbc.dbcp;
    import jdbc.utils.JDBCUtils_DBCP;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    //SQL语句删除操作
    public class DeleteSql {
        public static void main(String[] args) {
            Connection conn=null;
            PreparedStatement psta=null;
            ResultSet res=null;
            try {
                //获取数据库连接对象
                conn= JDBCUtils_DBCP.getConnection();
                //SQL语句字符串:使用占位符(?)代替参数
                String sql="delete from student where name=?";
                //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
                psta= conn.prepareStatement(sql);
                //手动给参数赋值,按照字段列的顺序一一对应
                psta.setString(1,"学海");
                int rn=psta.executeUpdate();//执行SQL语句
                if(rn>0){
                    System.out.println("删除数据成功");
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_DBCP.release(conn,psta,res);
            }
        }
    }
    

    其运行结果,如下所示

    删除数据成功
    
  • 20.4.1.2.3、改操作(Update操作)

    其示例代码,如下所示

    package jdbc.dbcp;
    import jdbc.utils.JDBCUtils_DBCP;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    //SQL语句修改操作
    public class UpdateSQL {
        public static void main(String[] args) {
            Connection conn=null;
            PreparedStatement psta=null;
            ResultSet res=null;
            try {
                //获取数据库连接对象
                conn= JDBCUtils_DBCP.getConnection();
                //SQL语句字符串:使用占位符(?)代替参数
                String sql="update student set name=? where name=?";
                //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
                psta= conn.prepareStatement(sql);
                //手动给参数赋值,按照字段列的顺序一一对应
                psta.setString(1,"学海");
                psta.setString(2,"学山");
                int rn=psta.executeUpdate();//执行SQL语句
                if(rn>0){
                    System.out.println("更新数据成功");
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_DBCP.release(conn,psta,res);
            }
        }
    }
    

    其运行结果,如下所示

    更新数据成功
    
  • 20.4.1.2.4、查操作(Retrieve操作)

    其示例代码,如下所示

    package jdbc.dbcp;
    import jdbc.utils.JDBCUtils_DBCP;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    //SQL语句查询操作
    public class SelectSql {
        public static void main(String[] args) {
            Connection conn=null;
            PreparedStatement psta=null;
            ResultSet res=null;
            try {
                //获取数据库连接对象
                conn= JDBCUtils_DBCP.getConnection();
                //SQL语句字符串:使用占位符(?)代替参数
                String sql="select name,pwd,sex,birthday,gradeid from student where name=?";
                //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
                psta= conn.prepareStatement(sql);
                //手动给参数赋值,按照字段列的顺序一一对应
                psta.setString(1,"张三");
                res=psta.executeQuery();//执行SQL语句
                while(res.next()){
                    System.out.println("name="+res.getString("name"));
                    System.out.println("pwd="+res.getString("pwd"));
                    System.out.println("sex="+res.getString("sex"));
                    System.out.println("birthday="+res.getDate("birthday"));
                    System.out.println("gradeid="+res.getInt("gradeid"));
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_DBCP.release(conn,psta,res);
            }
        }
    }
    

    其运行结果,如下所示

    name=张三
    pwd=12321
    sex=男
    birthday=2021-10-03
    gradeid=3
    
20.4.2、C3P0数据库连接池

前提条件:先导入对应jar包(即,c3p0-0.9.5.5.jar、mchange-commons-java-0.2.19.jar),具体操作请参考前面“导入数据库驱动文件(即,mysql-connector-java-5.1.47.jar)”操作

20.4.2.1、提取工具类

配置文件(c3p0-config.xml)内容,如下所示

<?xml version="1.0" encoding="UTF-8"?>
<!--此配置文件名必须为“c3p0-config”,且此配置文件放到工程“src”根目录下,否则无法正常加载使用-->
<c3p0-config>
    <!--
    C3P0的默认(缺省)配置:对应代码为“ComboPooledDataSource dataSource = new ComboPooledDataSource();”。
    -->
    <default-config>
        <!--数据库驱动名称-->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <!--url,其中特别注意的是:当数据库安装版本低于数据库驱动版本时“useSSL参数设定值”必须为"useSSL=true",否则必须为"useSSL=false"。-->
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_test?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false</property>
        <!--用户名-->
        <property name="user">root</property>
        <!--密码-->
        <property name="password">123456</property>
        <!--如果数据库连接池中数据连接不够时一次增长多少个-->
        <property name="acquireIncrement">5</property>
        <!--初始化数据库连接池数量-->
        <property name="initialPoolSize">10</property>
        <!--数据库连接池最大连接数量-->
        <property name="maxPoolSize">20</property>
        <!--数据库连接池最小连接数量-->
        <property name="minPoolSize">2</property>
        <!--每次最多可以执行多少个批处理语句-->
        <property name="maxStatements">30</property>
    </default-config>
    <!--
    C3P0的自定义命名配置:对应代码为“ComboPooledDataSource dataSource = new ComboPooledDataSource("MySQL");”。
    -->
    <named-config name="MySQL">
        <!--数据库驱动名称-->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <!--url,其中特别注意的是:当数据库安装版本低于数据库驱动版本时“useSSL参数设定值”必须为"useSSL=true",否则必须为"useSSL=false"。-->
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_test?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false</property>
        <!--用户名-->
        <property name="user">root</property>
        <!--密码-->
        <property name="password">123456</property>
        <!--如果数据库连接池中数据连接不够时一次增长多少个-->
        <property name="acquireIncrement">5</property>
        <!--初始化数据库连接池数量-->
        <property name="initialPoolSize">10</property>
        <!--数据库连接池最大连接数量-->
        <property name="maxPoolSize">20</property>
        <!--数据库连接池最小连接数量-->
        <property name="minPoolSize">2</property>
        <!--每次最多可以执行多少个批处理语句-->
        <property name="maxStatements">30</property>
    </named-config>
</c3p0-config>

JDBCUtils_C3P0工具类示例代码,如下所示

package jdbc.utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JDBCUtils_C3P0 {
    private static ComboPooledDataSource dataSource = null;
    //静态代码快(只会在第一次加载类时执行)
    static {
        try {
//            //方式一:代码配置版
//            dataSource=new ComboPooledDataSource();
//            dataSource.setDriverClass("");
//            dataSource.setJdbcUrl("");
//            dataSource.setUser("");
//            dataSource.setPassword("");
//            dataSource.setMaxPoolSize(20);
//            ......
            //方式二:xml文件配置版,创建数据源(数据库连接池):固定方式,使用工厂模式创建
            dataSource = new ComboPooledDataSource("MySQL");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取数据库连接
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();//从数据源(数据库连接池)中获取连接
    }
    //释放数据库连接对象资源
    public static void release(Connection conn, PreparedStatement psta, ResultSet res) {
        if (res != null) {
            try {
                res.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (psta != null) {
            try {
                psta.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}
20.4.2.2、实现增查删改操作
  • 20.4.2.2.1、增操作(Create操作)

    其示例代码,如下所示

    package jdbc.c3p0;
    import jdbc.utils.JDBCUtils_C3P0;
    import java.sql.*;
    //SQL语句增加操作
    public class InsertSql {
        public static void main(String[] args) {
            Connection conn=null;
            PreparedStatement psta=null;
            ResultSet res=null;
            try {
                //获取数据库连接对象
                conn= JDBCUtils_C3P0.getConnection();
                //SQL语句字符串:使用占位符(?)代替参数
                String sql="insert into student(name,pwd,sex,birthday,gradeid) values(?,?,?,?,?)";
                //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
                psta= conn.prepareStatement(sql);
                //手动给参数赋值,按照字段列的顺序一一对应
                psta.setString(1,"学山");
                psta.setString(2,"123456789");
                psta.setString(3,"男");
                /**
                 * 特别注意:
                 * 1、Java日期时间:java.util.Date(),Java时间戳:java.util.Date().getTime();
                 * 2、数据库日期时间:java.sql.Date();数据库时间戳:java.sql.Date().getTime();
                 */
                psta.setDate(4,new Date(new java.util.Date().getTime()));
                psta.setInt(5,1);
                int rn=psta.executeUpdate();//执行SQL语句
                if(rn>0){
                    System.out.println("插入数据成功");
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_C3P0.release(conn,psta,res);
            }
        }
    }
    

    其运行结果,如下所示

    1004, 2021 3:55:09 下午 com.mchange.v2.log.MLog 
    信息: MLog clients using java 1.4+ standard logging.
    1004, 2021 3:55:09 下午 com.mchange.v2.c3p0.C3P0Registry 
    信息: Initializing c3p0-0.9.5.5 [built 11-December-2019 22:07:46 -0800; debug? true; trace: 10]
    1004, 2021 3:55:09 下午 com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource 
    信息: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 5, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> MySQL, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 2t2kpaakkm5m7ikcfb80|9629756, idleConnectionTestPeriod -> 0, initialPoolSize -> 10, jdbcUrl -> jdbc:mysql://localhost:3306/jdbc_test?useUnicode=true&characterEncoding=utf8&useSSL=false, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 30, maxStatementsPerConnection -> 0, minPoolSize -> 2, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {password=******, user=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
    插入数据成功
    
  • 20.4.2.2.2、删操作(Delete操作)

    其示例代码,如下所示

    package jdbc.c3p0;
    import jdbc.utils.JDBCUtils_C3P0;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    //SQL语句删除操作
    public class DeleteSql {
        public static void main(String[] args) {
            Connection conn=null;
            PreparedStatement psta=null;
            ResultSet res=null;
            try {
                //获取数据库连接对象
                conn= JDBCUtils_C3P0.getConnection();
                //SQL语句字符串:使用占位符(?)代替参数
                String sql="delete from student where name=?";
                //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
                psta= conn.prepareStatement(sql);
                //手动给参数赋值,按照字段列的顺序一一对应
                psta.setString(1,"学海");
                int rn=psta.executeUpdate();//执行SQL语句
                if(rn>0){
                    System.out.println("删除数据成功");
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_C3P0.release(conn,psta,res);
            }
        }
    }
    

    其运行结果,如下所示

    1004, 2021 4:00:48 下午 com.mchange.v2.log.MLog 
    信息: MLog clients using java 1.4+ standard logging.
    1004, 2021 4:00:48 下午 com.mchange.v2.c3p0.C3P0Registry 
    信息: Initializing c3p0-0.9.5.5 [built 11-December-2019 22:07:46 -0800; debug? true; trace: 10]
    1004, 2021 4:00:48 下午 com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource 
    信息: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 5, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> MySQL, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 2t2kpaakkmcvq01omtpg3|9629756, idleConnectionTestPeriod -> 0, initialPoolSize -> 10, jdbcUrl -> jdbc:mysql://localhost:3306/jdbc_test?useUnicode=true&characterEncoding=utf8&useSSL=false, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 30, maxStatementsPerConnection -> 0, minPoolSize -> 2, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {password=******, user=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
    删除数据成功
    
  • 20.4.2.2.3、改操作(Update操作)

    其示例代码,如下所示

    package jdbc.c3p0;
    import jdbc.utils.JDBCUtils_C3P0;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    //SQL语句修改操作
    public class UpdateSQL {
        public static void main(String[] args) {
            Connection conn=null;
            PreparedStatement psta=null;
            ResultSet res=null;
            try {
                //获取数据库连接对象
                conn= JDBCUtils_C3P0.getConnection();
                //SQL语句字符串:使用占位符(?)代替参数
                String sql="update student set name=? where name=?";
                //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
                psta= conn.prepareStatement(sql);
                //手动给参数赋值,按照字段列的顺序一一对应
                psta.setString(1,"学海");
                psta.setString(2,"学山");
                int rn=psta.executeUpdate();//执行SQL语句
                if(rn>0){
                    System.out.println("更新数据成功");
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_C3P0.release(conn,psta,res);
            }
        }
    }
    

    其运行结果,如下所示

    1004, 2021 3:59:38 下午 com.mchange.v2.log.MLog 
    信息: MLog clients using java 1.4+ standard logging.
    1004, 2021 3:59:39 下午 com.mchange.v2.c3p0.C3P0Registry 
    信息: Initializing c3p0-0.9.5.5 [built 11-December-2019 22:07:46 -0800; debug? true; trace: 10]
    1004, 2021 3:59:39 下午 com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource 
    信息: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 5, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> MySQL, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 2t2kpaakkmbe2l1wto9dk|9629756, idleConnectionTestPeriod -> 0, initialPoolSize -> 10, jdbcUrl -> jdbc:mysql://localhost:3306/jdbc_test?useUnicode=true&characterEncoding=utf8&useSSL=false, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 30, maxStatementsPerConnection -> 0, minPoolSize -> 2, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {password=******, user=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
    更新数据成功
    
  • 20.4.2.2.4、查操作(Retrieve操作)

    其示例代码,如下所示

    package jdbc.c3p0;
    import jdbc.utils.JDBCUtils_C3P0;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    //SQL语句查询操作
    public class SelectSql {
        public static void main(String[] args) {
            Connection conn=null;
            PreparedStatement psta=null;
            ResultSet res=null;
            try {
                //获取数据库连接对象
                conn= JDBCUtils_C3P0.getConnection();
                //SQL语句字符串:使用占位符(?)代替参数
                String sql="select name,pwd,sex,birthday,gradeid from student where name=?";
                //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
                psta= conn.prepareStatement(sql);
                //手动给参数赋值,按照字段列的顺序一一对应
                psta.setString(1,"张三");
                res=psta.executeQuery();//执行SQL语句
                while(res.next()){
                    System.out.println("name="+res.getString("name"));
                    System.out.println("pwd="+res.getString("pwd"));
                    System.out.println("sex="+res.getString("sex"));
                    System.out.println("birthday="+res.getDate("birthday"));
                    System.out.println("gradeid="+res.getInt("gradeid"));
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally{
                JDBCUtils_C3P0.release(conn,psta,res);
            }
        }
    }
    

    其运行结果,如下所示

    1004, 2021 4:02:11 下午 com.mchange.v2.log.MLog 
    信息: MLog clients using java 1.4+ standard logging.
    1004, 2021 4:02:11 下午 com.mchange.v2.c3p0.C3P0Registry 
    信息: Initializing c3p0-0.9.5.5 [built 11-December-2019 22:07:46 -0800; debug? true; trace: 10]
    1004, 2021 4:02:11 下午 com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource 
    信息: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 5, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> MySQL, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 2t2kpaakkmenid9n5xs1|9629756, idleConnectionTestPeriod -> 0, initialPoolSize -> 10, jdbcUrl -> jdbc:mysql://localhost:3306/jdbc_test?useUnicode=true&characterEncoding=utf8&useSSL=false, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 30, maxStatementsPerConnection -> 0, minPoolSize -> 2, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {password=******, user=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
    name=张三
    pwd=12321
    sex=男
    birthday=2021-10-03
    gradeid=3
    

20.5、使用IDEA相关工具类操作数据库事务(Use IDEA Related Tool Classes Operation DataBase Transaction)

20.5.1、使用JDBCUtils_STA工具类操作数据库事务

其示例代码,如下所示

package jdbc.transaction;
import jdbc.utils.JDBCUtils_STA;
import java.sql.*;
//数据库事务操作
public class Transaction_STA {
    public static void main(String[] args) {
        Connection conn = null;
        Statement sta = null;
        ResultSet res = null;
        try {
            conn = JDBCUtils_STA.getConnection();//获取数据库连接对象
            conn.setAutoCommit(false);//关闭数据库事务的自动提交(默认参数为true就是代表自动提交事务)
            sta = conn.createStatement();//获得SQL语句指定对象
            String sql = "update student set name='学海' where name='学山'";//SQL语句字符串
            sta.executeUpdate(sql);//执行SQL语句
            sql = "update student set sex='女' where name='学海'";
            sta.executeUpdate(sql);
            conn.commit();//业务完成,提交事务
            System.out.println("事务提交成功");
        } catch (SQLException throwables) {
            try {
                throwables.printStackTrace();
                System.out.println("事务提交失败");
                conn.rollback();//业务失败,回滚事务
                System.out.println("事务回滚成功");
            } catch (SQLException e) {
                System.out.println("事务回滚失败");
                e.printStackTrace();
            }
        } finally {
            JDBCUtils_STA.release(conn, sta, res);
        }
    }
}

其运行结果,如下所示

事务提交成功
20.5.2、使用JDBCUtils_PSTA工具类操作数据库事务

其示例代码,如下所示

package jdbc.transaction;
import jdbc.utils.JDBCUtils_PSTA;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
//数据库事务操作
public class Transaction_PSTA {
    public static void main(String[] args) {
        Connection conn=null;
        PreparedStatement psta=null;
        ResultSet res=null;
        try {
            //获取数据库连接对象
            conn= JDBCUtils_PSTA.getConnection();
            //关闭数据库事务的自动提交(默认参数为true就是代表自动提交事务)
            conn.setAutoCommit(false);
            //SQL语句字符串:使用占位符(?)代替参数
            String sql="update student set name=? where name=?";
            //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
            psta= conn.prepareStatement(sql);
            //手动给参数赋值,按照字段列的顺序一一对应
            psta.setString(1,"学海");
            psta.setString(2,"学山");
            psta.executeUpdate();//执行SQL语句
            //SQL语句字符串:使用占位符(?)代替参数
            sql="update student set sex=? where name=?";
            //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
            psta= conn.prepareStatement(sql);
            //手动给参数赋值,按照字段列的顺序一一对应
            psta.setString(1,"女");
            psta.setString(2,"学海");
            psta.executeUpdate();//执行SQL语句
            conn.commit();//业务完成,提交事务
            System.out.println("事务提交成功");
        } catch (SQLException throwables) {
            try {
                throwables.printStackTrace();
                System.out.println("事务提交失败");
                conn.rollback();//业务失败,回滚事务
                System.out.println("事务回滚成功");
            } catch (SQLException e) {
                System.out.println("事务回滚失败");
                e.printStackTrace();
            }
        }finally{
            JDBCUtils_PSTA.release(conn,psta,res);
        }
    }
}

其运行结果,如下所示

事务提交成功
20.5.3、使用JDBCUtils_DBCP工具类操作数据库事务

其示例代码,如下所示

package jdbc.transaction;
import jdbc.utils.JDBCUtils_DBCP;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
//数据库事务操作
public class Transaction_DBCP {
    public static void main(String[] args) {
        Connection conn=null;
        PreparedStatement psta=null;
        ResultSet res=null;
        try {
            //获取数据库连接对象
            conn= JDBCUtils_DBCP.getConnection();
            //关闭数据库事务的自动提交(默认参数为true就是代表自动提交事务)
            conn.setAutoCommit(false);
            //SQL语句字符串:使用占位符(?)代替参数
            String sql="update student set name=? where name=?";
            //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
            psta= conn.prepareStatement(sql);
            //手动给参数赋值,按照字段列的顺序一一对应
            psta.setString(1,"学海");
            psta.setString(2,"学山");
            psta.executeUpdate();//执行SQL语句
            //SQL语句字符串:使用占位符(?)代替参数
            sql="update student set sex=? where name=?";
            //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
            psta= conn.prepareStatement(sql);
            //手动给参数赋值,按照字段列的顺序一一对应
            psta.setString(1,"女");
            psta.setString(2,"学海");
            psta.executeUpdate();//执行SQL语句
            conn.commit();//业务完成,提交事务
            System.out.println("事务提交成功");
        } catch (SQLException throwables) {
            try {
                throwables.printStackTrace();
                System.out.println("事务提交失败");
                conn.rollback();//业务失败,回滚事务
                System.out.println("事务回滚成功");
            } catch (SQLException e) {
                System.out.println("事务回滚失败");
                e.printStackTrace();
            }
        }finally{
            JDBCUtils_DBCP.release(conn,psta,res);
        }
    }
}

其运行结果,如下所示

事务提交成功
20.5.4、使用JDBCUtils_C3P0工具类操作数据库事务

其示例代码,如下所示

package jdbc.transaction;
import jdbc.utils.JDBCUtils_C3P0;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
//数据库事务操作
public class Transaction_C3P0 {
    public static void main(String[] args) {
        Connection conn=null;
        PreparedStatement psta=null;
        ResultSet res=null;
        try {
            //获取数据库连接对象
            conn= JDBCUtils_C3P0.getConnection();
            //关闭数据库事务的自动提交(默认参数为true就是代表自动提交事务)
            conn.setAutoCommit(false);
            //SQL语句字符串:使用占位符(?)代替参数
            String sql="update student set name=? where name=?";
            //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
            psta= conn.prepareStatement(sql);
            //手动给参数赋值,按照字段列的顺序一一对应
            psta.setString(1,"学海");
            psta.setString(2,"学山");
            psta.executeUpdate();//执行SQL语句
            //SQL语句字符串:使用占位符(?)代替参数
            sql="update student set sex=? where name=?";
            //获得SQL语句指定对象:预编译SQL,先写SQL,不执行SQL
            psta= conn.prepareStatement(sql);
            //手动给参数赋值,按照字段列的顺序一一对应
            psta.setString(1,"女");
            psta.setString(2,"学海");
            psta.executeUpdate();//执行SQL语句
            conn.commit();//业务完成,提交事务
            System.out.println("事务提交成功");
        } catch (SQLException throwables) {
            try {
                throwables.printStackTrace();
                System.out.println("事务提交失败");
                conn.rollback();//业务失败,回滚事务
                System.out.println("事务回滚成功");
            } catch (SQLException e) {
                System.out.println("事务回滚失败");
                e.printStackTrace();
            }
        }finally{
            JDBCUtils_C3P0.release(conn,psta,res);
        }
    }
}

其运行结果,如下所示

1004, 2021 4:42:08 下午 com.mchange.v2.log.MLog 
信息: MLog clients using java 1.4+ standard logging.
1004, 2021 4:42:08 下午 com.mchange.v2.c3p0.C3P0Registry 
信息: Initializing c3p0-0.9.5.5 [built 11-December-2019 22:07:46 -0800; debug? true; trace: 10]
1004, 2021 4:42:09 下午 com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource 
信息: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 5, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> MySQL, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 2t2kpaakknu1itbsr0ym|9629756, idleConnectionTestPeriod -> 0, initialPoolSize -> 10, jdbcUrl -> jdbc:mysql://localhost:3306/jdbc_test?useUnicode=true&characterEncoding=utf8&useSSL=false, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 30, maxStatementsPerConnection -> 0, minPoolSize -> 2, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {password=******, user=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
事务提交成功

参考资料(Reference Data):mySQLDQL、DML、DDL、DCL的概念与区别MD5事务ACID

学习网站地址(即"学习网址",Learning Website Address):Java之MySQL

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值