目录

写于

20210703

《MySQL》学习笔记 1 一、初识MySQL 1 1.1 为什么学习数据库 1 1.2 什么是数据库 1 1.3 数据库分类 1 关系型数据库(SQL) 1 非关系型数据库(NoSQL)Not Only SQL 2 DBMS(数据库管理系统) 2 1.4 MySQL简介 2 1.5 安装MySQL 2 1.6 安装SQLyog 3 1.7 连接数据库 4 二、操作数据库 4 2.1 操作数据库 4 1.创建数据库 4 2.删除数据库 5 3.使用数据库 5 4.查看数据库 5 2.2 数据库的列类型 5 数值 5 字符串 5 时间日期 5 Null 6 2.3 数据库的字段属性 6 Unsigned: 6 Zerofill 6 自增 6 非空Null not null 6 默认 6 2.4 创建数据库表 7 常用命令 7 2.5 数据表的类型 7 在物理空间对应的位置 8 MySQL引擎在物理文件上的区别 8 设置数据库表的字符集编码 8 2.6 修改删除表 8 修改 8 三、MySQL数据管理 9 3.1 外键 9 3.2 DML语言 9 3.3 添加 9 3.4 修改 10 3.5 删除 10 Delete和truncate的区别 10 四、DQL查询数据 10 4.1 DQL 10 4.2 查询指定字段 11 4.3 where条件子句 12 模糊查询:比较运算符 13 4.4 联表查询 13 4.5 分页和排序 14 4.6 子查 询 14 4.7 分组和过滤 14 5 MySQL函数 15 5.2 聚合函数 15 5.3 数据库级别的MD5加密 15 6 事务 15 6.1 什么是事务 15 模拟转账:事务 15 七 索引 16 7.1 索引的分类 16 7.2 测试索引 17 7.3 索引原则 17 8 数据库备份 17 8.1 用户管理 17 8.2 数据库备份 18 9 规范数据库设计 19 9.1 为什么需要设计 19 设计数据库的步骤(个人博客) 19 9.2 三大范式 19 10 JDBC(重点) 20 10.1 数据库驱动 20 10.2 JDBC 20 10.3 第一个JDBC程序 21 前期MySQL对象编程 22 Java编程连接 22 DriverManger 23 URL 24 10.4 statement对象 24 代码实现 25 SQL注入问题 30 10.5 PreparedStatement对象 31 1.新增 32 2.删除 33 3.修改 34 4.查询 35 10.6 使用IDEA连接数据库 36 连接失败问题 36 创建数据库表格信息 36 10.7 JDBC操作事务 37 10.8 数据库连接池 40 池化技术 40 开源数据源实现 40 DBCP 40 C3P0 44 结论 44

一、初识MySQL

JavaEE:企业级Java开发 Web 前端(页面:展示,数据) 后台(连接点:连接数据库JDBC,链接前端(控制,控制视图跳转和给前端传递数据)) 数据库:存数据,TXT,Excel,word 只会写代码,学好数据库,基本混饭吃 操作系统,数据结构与算法,当一个不错的程序猿 离散数学,数字电器,体系结构,编译原理+实战经验,高级程序猿-优秀的程序猿

1.1 为什么学习数据库

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

1.2 什么是数据库

数据库(DB,DataBase) 概念:数据仓库,软件,安装在操作系统(window,linux,mac……)之上,SQL,可以存储大量的数据,500万以下 作用:存储数据,管理数据

1.3 数据库分类

关系型数据库(SQL)

行、列 常见:MySQL、Oracle、Sql Server,DB2,SQLlite 通过表和表之间,行和列之间的关系进行数据的存储 学员信息表,考勤表

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

Redis,MongDB 对象存储,通过对象的自身的属性来决定

DBMS(数据库管理系统)

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

1.4 MySQL简介

百度百科:MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。 MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。 MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言。MySQL 软件采用了双授权政策,分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型网站的开发都选择 MySQL 作为网站数据库。

1.5 安装MySQL

尽量不要安装exe版本 安装压缩包 1.解压 2.把解压包放到自己的电脑文件下 3.配置环境变更量 4.新建mysql配置文件ini

[mysqld]
basedir=D:\Environment\mysql-5.7.19\
datadir=D:\Environment\mysql-5.7.19\data\
port=3306
skip - grant - tables

目录换成自己的 5.启动管理员模式下的CMD,运行所有命令 6.安装mySQL服务 7.初始化数据库文件 8.启动mysql,进去修改密码 9.进入mysql通过命令行,修改密码 10.注释掉ini的跳过密码 11.重启sql,连接测试 安装过程中常见问题 1.缺少组件 2.命令出错

1.6 安装SQLyog

1.安装 2.注册 3.打开连接数据库 4.新建数据库

image-20250505202415641

每一个sqlyog 5.新建一张表 student image-20250505202430436 6.查看表 7.尝试添加多个数据

1.7 连接数据库

命令行连接

mysql –uroot –p(密码) –-连接数据库

update mysql.user set authentication_string=password('123456') where user='root' and Host = 'localhost'; --修改用户密码

flush privileges; -- 刷新权限

------------------------

–所有的语句都要以分号结尾

show databases; --显示所有的数据库存

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

Database changed

show tables; -- 查看数据库中所有的表

describe student; --显示数据库中所有表的信息

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

exit; --退出连接


–- 单行注释

多行注释/ / 数据库XX语言,CRUD,增删改查 DDL,数据库定义语言 DML,数据库操作语言 DQL,查询 DCL,控制

二、操作数据库

操作数据库 > 操作数据库中的表 > 操作数据库中表的数据 Mysql中命令不区别大小写

2.1 操作数据库

1.创建数据库

CREATE DATABASE IF NOT EXISTS westos

2.删除数据库

DROP DATABASE IF EXISTS hello

3.使用数据库

    • tab键的上面,如果有特殊字符,需要带` USEschool`

4.查看数据库

SHOW DATABASES -- 显示所有数据库 对比:sqlyog的可视化操作 学习思路:对照sqlyog可视化历史记录查看sql 固定的语法或关键词必须要强行记住

2.2 数据库的列类型

数值

Tinyint 十分小的数据 1个字节 Smallint 较小的数据 2个字节 Mediumint 中等的数据 3个字节 Int 标准的整数 4个字节 Bigint 较大的数据 8个字节 Float ,浮点数,4个字节 Double,双精度数,8个字节 Decimal 字符串形式的浮点数,金融计算时一般使用

字符串

Char,字符串,固定大小的0-255 Varchar,可变字符串,0~65535,常用的string 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进行运算

2.3 数据库的字段属性

重点

Unsigned:

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

Zerofill

0填充,不足的位数为0填充

自增

通常理解为自动在上一条记录的基础上+1(默认) 通常用来设计唯一的主键,必须是整数类型 也可以自己设置主键自增的初始值和步长

非空Null not null

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

默认

设置默认的值 Sex,默认值为男,如果不指定该列的值,则会一直默认为男 /* 每一个表,都必须存在以下五个字段!未来做项目用的,表示一个记录存在意义 id 主键 version 乐观锁 is_delete 伪删除 gmt_create 创建时间 gmt_update 更新时间 - /

2.4 创建数据库表

- 目标:创建一个school数据库

- 创建学生表(列,字段) 使用sql创建

- 注意,使用英文特号,表的名称和字段尽量用``括起来

- AUTO_INCREMENT 自增

- 字符串使用单引号括起来!

- 所有的语句后面加英文逗号,最后一个字段不加

DROP TABLE IF EXISTS student

CREATE TABLE IF NOT EXISTS `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] 表名(

字段名 列类型 [属性] [索引] [注释],

字段名 列类型 [属性] [索引] [注释],

……

字段名 列类型 [属性] [索引] [注释]

)[表类型][字符集设置][注释]

常用命令

  1. SHOW CREATE DATABASE school -- 查看创建数据库语句
  2. SHOW CREATE TABLE student -- 查看数据表的定义语句
  3. DESC student -- 显示表的结构

2.5 数据表的类型

  1. - 关于数据库引擎
  2. /*
  3. innodb 默认使用
  4. myisam 早些年使用
特性 MYISAM INNODB
事务支持 不支持 支持
数据行锁定 不支持 支持
外键约束 不支持 支持
全文索引 支持 不支持
表空间的大小 较小 较大,约为 2 倍

常规使用操作:

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

在物理空间对应的位置

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

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

InnoDB在数据库表中只有一个.frm文件,以及上级目录下的ibdata1文件 MYISAM对应文件:.frm – 表结构的定义文件;.myd – 数据文件(data);.myi – 索引文件(index)

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

CHARSET=utf8 不设置,会是MYSQL默认的字符集(不支持中文)

2.6 修改删除表

修改

修改表名:ALTER TABLE 旧表名 RENAME AS 新表名

ALTER TABLE student1 RENAME AS student

增加表的字段:ALTER TABLE 表名 ADD 字段名 列属性

ALTER TABLE student ADD age INT (11)

修改表的字段(重命名,修改约束!)

ALTER TABLE student MODIFY age VARCHAR (11) -- 修改约束
ALTER TABLE student CHANGED age age1 INT (1) -- 字段重命名

删除表的字段

ALTER TABLE student DROP age1

删除

  • 删除表(如果表存在再删除)

DROP TABLE IF EXISTS teacher1

注意点:所有创建和删除尽量加上判断,以免出错 1.`` 字段名,使用这个包括 2.注释 -- / / 3.sql关键词大小写敏感,写英文

三、MySQL数据管理

3.1 外键

方式一:在创建表的时候,增加约束、外键 方式二:删除有外键关系的表时,必须要先删除引用别人的表,再删除被引用的表 以上创建的都是物理外键,数据库级别的外键,我们不建议使用(避免过多数据库造成困扰) 最佳实践: 数据库就是单纯的表,只用来存数据,只有行和列

3.2 DML语言

数据库意义:数据存储,数据管理 DML语言:数据操作语言 Insert Update drop

3.3 添加

Insert into 表名([字段名1,字段2,字段3]) values (值1,值2,……) 写入语句时,数据和字段和一一对应 插入多个字段 注意事项: 1、字段和字段之间使用英文逗号隔开 2、字段可以省略,但后面的值必须要一一对应,不能少 3、可以同时插入多条数据,values 后面的值,需要使用,隔开即可

3.4 修改

Update-更新-修改 不指定条件的情况下,会改动所有表 修改多个属性,逗号隔开 语法:Update 表名 set column_name = value where [条件] 条件:where子句,运算符 id等于某个值,大于某个值,在某个区间内修改;筛选的条件,如果没有指定,则会修改所有的列 Value,可以是一个具体的值,也可以是一个变量 多个设置的属性,使用英文逗号隔开

3.5 删除

语法:delete from 表名 [where 条件] Truncate命令 作用:完全清空一个数据库表,表的结构和索引不会变

Delete和truncate的区别

Truncate 重新设置 自增列 计数器会归零 Truncate 不会影响事务 Delete删除的问题,重启数据库后的现象 innoDB 自增列从1开始(存在内存中,断电即失) MyISAM,继续从上一个自增量开始,(存在文件中,不会丢失)

四、DQL查询数据

4.1 DQL

Data query language ,数据查询语言 所有的查询操作都用它,select 简单、复杂的查询它都能用 数据库中最核心的语句 使用频率最高的语句 查询全部的学生

Select * from student

查询指定字段 Select

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

-- 查询指定字段
SELECT `StudentNo`, `StudentName` FROM student

-- 别名,给结果起一个名字 AS 可以给字段起别名,也可以给表起别名
SELECT `StudentNo` AS 学号, `StudentName` AS 学生姓名 FROM student AS s

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

语法:SELECT 字段,... FROM 表

有的时候,我们可以起别字,as

-- 查询全部的学生
SELECT * FROM student;

-- 查询指定字段
SELECT `StudentNo`, `StudentName` FROM student;

-- 别名,给结果起一个名字
-- AS可以给字段起别名,也可以给表起别名
SELECT `StudentNo` AS 学号, `StudentName` AS 学生姓名 FROM student AS s;

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

4.2 查询指定字段

Select * from result

Select distinct `student` from result –发现重复数据,去重

去重 distinct

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

代码示例:

-- 查询一下有哪些同学参加了考试,成绩
SELECT * FROM result -- 查询全部的考试成绩
SELECT `StudentNo` FROM result -- 查询有哪些同学参加了考试
SELECT DISTINCT `StudentNo` FROM result -- 发现重复数据,去重

数据库的列(表达式)

代码示例:

SELECT VERSION() -- 查询系统版本(函数)
SELECT 100*3-1 AS 计算结果 -- 用来计算(表达式)
SELECT @@auto_increment_increment -- 查询自增的步长(变量)
-- 学员考试成绩 + 1分查看
SELECT `StudentNo`, `StudentResult`+1 AS '提分后' F

SELECT VERSION() SELECT 100*3-1 AS 计算结果 语法:Select 表达式 from 表 数据库中的表达式:文本值,列,Null,函数,计算表达式,系统变量……

4.3 where条件子句

作用:检索数据中符合条件的值 逻辑运算符

-- 查询考试成绩在95 - 100分之间
SELECT studentNo, `studentResult` FROM result
WHERE studentResult>=95 AND studentResult<=100;

-- 用&&表示and的等价查询
SELECT studentNo, `studentResult` FROM result
WHERE studentResult>=95 && studentResult<=100;

-- 模糊查询(区间),使用BETWEEN AND
SELECT studentNo, `studentResult` FROM result
WHERE studentResult BETWEEN 95 AND 100;

-- 除了1000号学生之外的同学的成绩
SELECT studentNo, `studentResult` FROM result
WHERE studentNo!=1000;

-- 用NOT表示不等的等价查询
SELECT studentNo, `studentResult` FROM result
WHERE NOT studentNo = 1000;

模糊查询:比较运算符

运算符 语法 描述
IS NULL a is null 如果操作符为 NULL,结果为真
IS NOT NULL a is not null 如果操作符不为 null,结果为真
BETWEEN a between b and c 若 a 在 b 和 c 之间,则结果为真
Like a like b SQL 匹配,如果 a 匹配 b,则结果为真
In a in (a1,a2,a3...) 假设 a 在 a1,或者 a2... 其中的某一个值中,结果为真

SELECT * FROM school.test; select 题号,题型,题目,A,B,C,D,难度 from school.test where 题号 between 10 and 20;

    • 查询101,102,103题号信息alter select 题号,题型,题目,A,B,C,D,难度 from school.test where 题号 in (101,102,103);

4.4 联表查询

join对比 image-20250505204308745

4.5 分页和排序

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

4.6 子查询

本质:在where语句中嵌套一个子查询语句 Where (select * from)

4.7 分组和过滤

-- 查询不同课程的平均分,最高分,最低分,平均分大于80
-- 核心:(根据不同的课程分组)
SELECT SubjectName, AVG(StudentResult) AS 平均分, MAX(StudentResult) AS 最高分, MIN(StudentResult) AS 最低分
FROM result r
INNER JOIN `subject` sub
ON r.`SubjectNo` = sub.`SubjectNo`
GROUP BY r.SubjectNo -- 通过什么字段来分组
HAVING 平均分>80

5 MySQL函数

MySQL 5.7参考手册

5.2 聚合函数

-- 聚合函数
-- 都能够统计 表中的数据 ( 想查询一个表中有多少个记录,就使用这个count() )
SELECT COUNT(`Borndate`) FROM student; -- Count(字段),会忽略所有的 null 值
SELECT COUNT(*) FROM student; -- Count(*),不会忽略 null 值,本质 计算行数
SELECT COUNT(1) FROM result; -- Count(1),不会忽略所有的 null 值 本质 计算行数

SELECT SUM(`studentResult`) AS 总和 FROM result
SELECT AVG(`studentResult`) AS 平均分 FROM result
SELECT MAX(`studentResult`) AS 最高分 FROM result
SELECT MIN(`studentResult`) AS 最低分 FROM result

5.3 数据库级别的MD5加密

MD5,主要增强,不可逆 MD5破解网站的原理,背后一个字典

6 事务

6.1 什么是事务

要么都成功,要么都失败 将一组SQL放在一个批次中去执行 事务原则:ACID原则,原子性atomicity,一致性consistency,隔离性isolation,持久性durability

模拟转账:事务

create database shop character set utf8 collate utf8_general_ci;

use shop;

create table `account`(

`id` int(3) not null auto_increment,

`**name**` varchar(30) not null,

`money` decimal(9,2) not null,

primary key (`id`)

)engine = InnoDB default charset=utf8;

insert into account(`**name**`,`money`)

values ('A', '2000'),('B', '3000');

- 模拟转账:事务alter

set autocommit = 0 ; -- 关闭自动提交alter

start transaction; -- 开启一个事务alter

update account set money=money-500 where 'name' = 'A';

update account set money=money+500 where 'name' = 'B';

commit; -- 提交事务alterr

rollback; -- 回滚alter

set autocommit = 1; -- 恢复默认值

七 索引

索引是帮助MySQL高效获取数据的内容

7.1 索引的分类

  • 主键索引primary key 唯一的标记,不可重复,只能有一个列作为主键
  • 唯一索引unique key 避免重复的列出现,可以有多个唯一索引,多个列可以标识为唯一索引
  • 普通索引key/index 默认的
  • 全文索引FullText

7.2 测试索引

-- 显示所有的索引信息
SHOW INDEX FROM student;

-- 增加一个全文索引(索引名 列名)
ALTER TABLE school.student ADD FULLTEXT INDEX `studentName`(`studentName`);

-- EXPLAIN 分析sql执行的状况
-- 非全文索引
EXPLAIN SELECT * FROM student;

-- 利用全文索引进行查询并分析执行状况
EXPLAIN SELECT * FROM student WHERE MATCH(studentName) AGAINST('刘');

索引在小数据量时用处不大,用处不大 但在大数据量时,区别较大

7.3 索引原则

索引不是越多越好 不要对经常变动的数据加索引 小数据量的表不需要加索引 索引一般加在常用来查询的字段上 索引的数据结构 hash类型的索引 btree:InnoDB的默认数据结构

8 数据库备份

8.1 用户管理

- 创建用户

create user xiaofei identified by '123456';

- 修改当前用户密码

set password = ***'111111');

- 修改指定用户密码

set password for xiaofei = password('123456');

- 重命名

rename user xiaofei to xiaofei2;

- 用户授权

grant all privileges on . to xiaofei2;

- 查询权限alter

show grants for xiaofei2;

show grants for root@loaclhost;

- 撤消权限

revoke all privileges on . from xiaofei2;

- 删除用户

drop user xiaofei2

8.2 数据库备份

保证重要数据不丢失 数据转移 - MySQL数据库备份的方式 直接拷备物理文件 在可视化工具中手动导出 使用命令行导出,mysqldump命令行使用

导出单个表

mysqldump -hlocalhost -uroot -p123456 school student >D:/a.sql
mysqldump -hlocalhost -uroot -p123456 school student >D:/b.sql

导出整个数据库

mysqldump -hlocalhost -uroot -p123456 school >D:/c.sql

导入数据(在登录 MySQL 且切换到指定数据库后)

source d:/a.sql

导入数据(另一种方式,不登录 MySQL 直接导入)

mysql -u用户名 -p密码 库名< 备份文件

需注意,实际使用时要将-u后的用户名、-p后的密码 替换为真实信息,库名替换为目标数据库名 。

  • 假设你要备份数据库,直接导出数据库文件便可

9 规范数据库设计

9.1 为什么需要设计

当数据库比较复杂时,我们需要设计 - 糟糕的数据库设计: 数据冗余,浪费空间 数据库插入和删除都会麻烦、异常(屏蔽使用物理外键) 程序的性能差 - 良好的数据库设计: 节省内存空间 保证数据库的完整性 方便我们使用开发系统 - 软件开发中,关于数据库的设计: 1.分析需求: 2.概要设计:设计关系图E-R图

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

  • 收集信息,分析需求 用户表 分类表 文章表 友链表 自定义表
  • 标识实体(把需求落地到具体)
  • 标识实体之间的关系 写博客:user blog 评论: user comment

9.2 三大范式

一、为什么数据要规范化: 1.信息重复 2.更新异常 3.插入异常,无法正常显示信息 4.删除异常 二、三大范式 第一范式(1NF):原子性,要求数据库中的每一列都是不可再分 第二范式(2NF):满足第一范式的前提下,每张表只描述一件事 第三范式(3NF):满足第二范式的前提下,每一列数据都和主键相关,不能间接相关 三、规范性和性能的问题 关联查询的表不得超过三张表 考虑商业化的需求和目标,数据库的性能更加重要 在规范性能的问题时,需要适当考虑一下规范性 可以增加一些冗余 增加一些计算列,从大数据量降低为小数据量

10 JDBC(重点)

10.1 数据库驱动

程序会通过数据库驱动,和数据库打交道 image-20250505205124359

10.2 JDBC

为了简化开发人员对数据库的操作,提供了一个数据库驱动规范,俗称jdbc image-20250505205139606 Java.sql Javax.sql 还需要导入一个数据库驱动包 mysql-connector-java-5.1.47.jar

10.3 第一个JDBC程序

步骤总结: 1.加载驱动 2.连接数据库DriverManger 3.获得执行sql的对象 statement 4.获得返回的结果集 5.释放连接

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

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

        //2. 用户信息和url
        // useUnicode=true&characterEncoding=utf8&useSSL=true
        String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
        String username = "root";
        String password = "***";
        //3. 连接成功,数据库对象 Connection 代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

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

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

        ResultSet resultSet = statement.executeQuery(sql); //返回的结果集,结果集中封装了我们全部的查询出来的结果

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

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

前期MySQL对象编程

show databases;

create database jdbcStudy character set utf8 collate utf8_general_ci;

use jdbcStudy;

create table users(

id int primary key,

name varchar(40),

password varchar(40),

email varchar(60),

birthday date

);

insert into users(id,name,password,email,birthday)

values(1,'zhansan','123456','z***@sina.com','1980-12-04'),

(2,'lisi','123456','l***@sina.com','1981-12-04'),

(3,'wangwu','123456','w***@sina.com','1979-12-04');

Java编程连接

**package lesson01;**

**import java.sql.Connection;**

**import java.sql.DriverManager;**

**import java.sql.ResultSet;**

**import java.sql.Statement;**

**/****

* **@Auther: fei**

* **@Date: 2021/7/2 - 07 - 02 - 20:19**

* **@Description: lesson01**

* **@version: 1.0**

***/**

**public class FirstDemo {**

**//这是一个main方法,是程序的入口:**

**public static void main(String[] args) throws Exception {**

**//1.加载驱动**

**Class.forName("com.mysql.jdbc.Driver");**

**//2.用户信息**

**// jdbc:mysql://localhost:3306/jdbcstudy 协议连接数据库jdbcstudy**

**// useSSL=false 不使用ssh**

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

**String username = "root";**

**String password = "***";**

**//3.连接数据库对象**

**Connection connection = DriverManager.getConnection(url, username, password);**

**//4.执行SQL的对象**

**Statement statement = connection.createStatement();**

**String sql = "select * from users";**

**ResultSet resultSet = statement.executeQuery(sql);**

**while(resultSet.next()){**

**System.out.println("id=" + resultSet.getObject("id"));**

**System.out.println("name=" + resultSet.getObject("name"));**

**System.out.println("password= "***"password"));**

**System.out.println("email=" + resultSet.getObject("email"));**

**System.out.println("birthday=" + resultSet.getObject("birthday"));**

**}**

**//5.释放链接**

**resultSet.close();**

**statement.close();**

**connection.close();**

**}**

**}**

DriverManger

  1. //1.加载驱动
  2. Class.forName("com.mysql.jdbc.Driver"); //固定写法,加载驱动 对于5.0版本,是这样写。对于更高版本,加载方式不同,参与网络

URL

  1. //2.用户信息
  2. //mysql --端口号3306
  3. // jdbc:mysql://localhost:3306/jdbcstudy 协议连接数据库jdbcstudy
  4. // useSSL=false 不使用ssh
  5. // (协议)jdbc:mysql://主机地址:端口号/数据库名?参数1&参数2&参数3
  6. //oracle --1521
  7. // jdbc:oracle:thin:@localhost:1521:sid
  8. String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false";

获得指定的数据类型

  • 文字说明:ResultSet是查询的结果集,封装了所有的查询结果。当不知道列类型时,可以使用getObject()方法获取数据;如果明确知道列的类型,则可使用对应的类型方法获取数据,比如getString()获取字符串类型数据、getInt()获取整数类型数据、getFloat()获取浮点类型数据、getDate()获取日期类型数据等。
  • 代码示例:
// 在不知道列类型的情况下使用
resultSet.getObject(); 
// 如果知道列的类型就使用指定的类型
resultSet.getString();
resultSet.getInt();
resultSet.getFloat();
resultSet.getDate();
resultSet.getObject();

遍历,指针

  • 文字说明:可以通过一些方法移动ResultSet的指针来遍历结果集。beforeFirst()将指针移动到最前面;afterLast()将指针移动到最后面;next()把指针移动到下一个数据;previous()将指针移动到前一行;absolute(row)则是把指针移动到指定行(row为指定的行号) 。
  • 代码示例:
resultSet.beforeFirst(); // 移动到最前面
resultSet.afterLast(); // 移动到最后面
resultSet.next(); //移动到下一个数据
resultSet.previous(); //移动到前一行
resultSet.absolute(row); //移动到指定行

上述代码中,resultSet为ResultSet类型对象,实际使用时需确保在合适的 JDBC 操作流程中调用这些方法,并且absolute(row)中的row要根据实际需求传入合法行号 。

10.4 statement对象

在 JDBC(Java Database Connectivity,Java 数据库连接)中,Statement对象的作用是向数据库发送 SQL 语句。若要实现对数据库的增、删、改、查操作,可借助该对象来发送相应的 SQL 语句。

Statement对象的executeUpdate方法,专门用于向数据库发送增加、删除、修改的 SQL 语句。在executeUpdate方法执行完毕后,会返回一个整数,该整数表示增删改语句在数据库中导致数据发生变化的行数。

而Statement的executeQuery方法,则是用于向数据库发送查询语句,此方法执行后会返回一个代表查询结果的ResultSet对象 。

代码实现

1.提取工具类

package utils;

import java.io.IOException;

import java.io.InputStream;

import java.sql.*;

import java.util.Properties;

/**

* @Auther: fei

* @Date: 2021/7/2 - 07 - 02 - 21:44

* @Description: utils

* @version: 1.0

*/

public class JdbcUtils {

private static String driver = null;

private static String url = null;

private static String username = null;

private static String password = ***;

static {

try {

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

Properties properties = new Properties();

properties.load(in);

driver = properties.getProperty("driver");

url = properties.getProperty("url");

username = properties.getProperty("username");

password = ***"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 st, ResultSet rs) {

if (rs != null) {

try {

rs.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

if (st != null) {

try {

st.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

if (conn != null) {

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

}

2.编写增删改的方法,executeUpdate

1. package lesson02;

3. import utils.JdbcUtils;
5. import java.sql.Connection;
6. import java.sql.ResultSet;
7. import java.sql.SQLException;
8. import java.sql.Statement;

10. /**
11. * @Auther: fei
12. * @Date: 2021/7/2 - 07 - 02 - 21:56
13. * @Description: lesson02
14. * @version: 1.0
15. */
16. public class TestInsert {
17.     //这是一个main方法,是程序的入口:
18.     public static void main(String[] args) {
19.         Connection conn = null;
20.         Statement st = null;
21.         ResultSet rt = null;
22.         try {
23.             conn = utils.JdbcUtils.getConnection();//获取数据库连接
24.             st = conn.createStatement();//获取SQL的执行对象
25.             String sql = "insert into users(id, `name`,`password`,`email`,`birthday`)" +
26.                     "values(4,'xiaofei','123456','4***@qq.com','1990-4-1')";

28.             int i = st.executeUpdate(sql);
29.             if(i > 0){
30.                 System.out.println("插入成功!");
31.             }
32.         } catch (SQLException e) {
33.             e.printStackTrace();
34.         }finally{
35.             utils.JdbcUtils.release(conn,st,rt);
36.         }
37.     }
38. }
39. package lesson02;

41. import utils.JdbcUtils;
43. import java.sql.Connection;
44. import java.sql.ResultSet;
45. import java.sql.SQLException;
46. import java.sql.Statement;

48. /**
49. * @Auther: fei
50. * @Date: 2021/7/2 - 07 - 02 - 21:56
51. * @Description: lesson02
52. * @version: 1.0
53. */
54. public class TestDelete {
55.     //这是一个main方法,是程序的入口:
56.     public static void main(String[] args) {
57.         Connection conn = null;
58.         Statement st = null;
59.         ResultSet rt = null;
60.         try {
61.             conn = utils.JdbcUtils.getConnection();//获取数据库连接
62.             st = conn.createStatement();//获取SQL的执行对象
63.             String sql = "delete from users where id = 4";

65.             int i = st.executeUpdate(sql);
66.             if(i > 0){
67.                 System.out.println("删除成功!");
68.             }
69.         } catch (SQLException e) {
70.             e.printStackTrace();
71.         }finally{
72.             utils.JdbcUtils.release(conn,st,rt);
73.         }
74.     }
75. }
76. package lesson02;

78. import java.sql.Connection;
79. import java.sql.ResultSet;
80. import java.sql.SQLException;
81. import java.sql.Statement;

83. /**
84. * @Auther: fei
85. * @Date: 2021/7/2 - 07 - 02 - 22:19
86. * @Description: lesson02
87. * @version: 1.0
88. */
89. public class TestUpdate {
90.     //这是一个main方法,是程序的入口:
91.     public static void main(String[] args) {
92.         Connection conn = null;
93.         Statement st = null;
94.         ResultSet rt = null;
95.         try {
96.             conn = utils.JdbcUtils.getConnection();//获取数据库连接
97.             st = conn.createStatement();//获取SQL的执行对象
98.             String sql = "update users set `name`='xiaofei' where id=1";

100.             int i = st.executeUpdate(sql);
101.             if(i > 0){
102.                 System.out.println("更新成功!");
103.             }
104.         } catch (SQLException e) {
105.             e.printStackTrace();
106.         }finally{
107.             utils.JdbcUtils.release(conn,st,rt);
108.         }
109.     }
110. }

3.查询executeQuery

1. package lesson02;
3. import java.sql.Connection;
4. import java.sql.ResultSet;
5. import java.sql.SQLException;
6. import java.sql.Statement;

/**
 * @Auther: fei
 * @Date: 2021/7/2 - 07 - 02 - 22:26
 * @Description: lesson02
 * @version: 1.0
 */
public class TestSelect {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try {
            conn = utils.JdbcUtils.getConnection();
            st = conn.createStatement();

            //SQL
            String sql = "select * from users where id = 1";
            rs = st.executeQuery(sql);

            while(rs.next()){
                System.out.println(rs.getString("name"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            utils.JdbcUtils.release(conn,st,rs);
        }
    }
}

SQL注入问题

Sql存在漏洞,会被攻击导致数据泄漏,主要是sql会被拼接 or

package lesson02;

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

/**

 * @Auther: fei

 * @Date: 2021/7/3 - 07 - 03 - 8:58

 * @Description: lesson02

 * @version: 1.0
   */
   public class SQLInject {
   //这是一个main方法,是程序的入口:
   public static void main(String[] args) {
       //login("xiaofei","123456");
       login(" 'or' 1=1","'or' 1=1"); //输入这个命令能将所有信息导出
   }

   //登录业务
   public static void login(String username,String password){
       // 声明连接相关的引用变量
       Connection conn = null;
       Statement st = null;
       ResultSet rs = null;

try {
    // 获取数据库连接
    conn = JdbcUtils.getConnection();
    // 创建Statement对象
    st = conn.createStatement();

    // 构建SQL查询语句
    //select * from users where`name` = 'xiaofei' and `password`= '123456'
    String sql = "select * from users where `name` = '" + username + "' and `password` = '" + password + "'";

    // 执行查询
    rs = st.executeQuery(sql);

    // 遍历结果集
    while(rs.next()){
        System.out.println(rs.getString("name"));
        System.out.println("password"); 
    }
} catch (SQLException e) {
    // 打印SQL异常堆栈信息
    e.printStackTrace();
} finally {
    // 释放数据库资源
    JdbcUtils.release(conn,st,rs);
        }
    }
}

10.5 PreparedStatement对象

PreparedStatement可以防止SQL注入,效率更好

1.新增

package lesson03;

import utils.JdbcUtils;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * 测试数据库插入操作的类
 */
public class TestInsert {
    public static void main(String[] args) {
        // 声明连接和预处理语句对象
        Connection conn = null;
        PreparedStatement st = null;
        try {
            // 获取数据库连接
            conn = JdbcUtils.getConnection();

            // SQL插入语句,使用预编译防止SQL注入
            String sql = "insert into users(id,`name`,`password`,`email`,`birthday`) values(?,?,?,?,?)";
            st = conn.prepareStatement(sql);

            // 设置参数值
            st.setInt(1, 4);
            st.setString(2, "xiao");
            st.setString(3, "123123");
            st.setString(4, "4***@qq.com");
            // 将Java日期转换为SQL日期
            st.setDate(5, new java.sql.Date(new java.util.Date().getTime()));

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

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 释放资源
            JdbcUtils.release(conn, st, null);
        }
    }
}

2.删除

package lesson03;

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

/**
 * @Auther: fei
 * @Date: 2021/7/3 - 07 - 03 - 9:51
 * @Description: lesson03
 * @version: 1.0
 */
public class TestDelete {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;

        try {
            conn = JdbcUtils.getConnection();
            //区别
            //使用?点位符代替参数
            String sql = "delete from users where id=?";
            st = conn.prepareStatement(sql);//预编译sql,先写sql,但不执行

            //手动赋参数
            st.setInt(1,4);

            //执行
            int i = st.executeUpdate();
            if(i>0){
                System.out.println("删除成功!");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,null);
        }
    }
}

3.修改

package lesson03;

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

/**
 * @Auther: fei
 * @Date: 2021/7/3 - 07 - 03 - 9:51
 * @Description: lesson03
 * @version: 1.0
 */
public class TestUpdate {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;

        try {
            conn = JdbcUtils.getConnection();

            //区别
            //使用?点位符代替参数
            String sql = "update users set `name`=? where id=?;";
            st = conn.prepareStatement(sql);//预编译sql,先写sql,但不执行

            //手动赋参数
            st.setString(1,"fei");
            st.setInt(2,1);

            //执行
            int i = st.executeUpdate();
            if(i>0){
                System.out.println("更新成功!");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,null);
        }
    }
}

4.查询

package lesson03;

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

/**
 * @Auther: fei
 * @Date: 2021/7/3 - 07 - 03 - 9:57
 * @Description: lesson03
 * @version: 1.0
 */
public class TestQuery {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();
            String sql = "select * from users where id = ?";
            st = conn.prepareStatement(sql);
            st.setInt(1,2);
            rs = st.executeQuery();
            if(rs.next()){
                System.out.println(rs.getString("name"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}

10.6 使用IDEA连接数据库

连接失败问题

没有设置环境变量 没有设置时区 连接成功后,可以选择数据库 编写sql代码 image22

创建数据库表格信息

use jdbcstudy;

create table account(
    id int primary key auto_increment,
    name varchar(40),
    money float
);

insert into account(name, money) values('A', 1000);
insert into account(name, money) values('B', 1000); 
insert into account(name, money) values('C', 1000);

10.7 JDBC操作事务

ACID原则 原子性:要么都完成,要么都不完成 一致性:总数不变 隔离性:多个进程互不干扰 持久性:一旦提交不可逆 隔离性的问题: 脏读:一个事务读取了另一个没有提交的事务 不可重复读:在同一个事务内,重复读取表中的数据,表数据发生了改变 虚读(幻读):在一个事务内,读取了别人插入的数据,导致前后读出来的结果不一致 代码 1.开启事务 2.一组业务执行完毕,提交事务 3.可以在catch语句中显示定义的回滚语句,但默认失败就会回滚 成功情况

package lesson04;

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

/**

 * @Auther: fei

 * @Date: 2021/7/3 - 07 - 03 - 15:28

 * @Description: lesson04

 * @version: 1.0
   */
   public class TestTransation {
   //这是一个main方法,是程序的入口:
   public static void main(String[] args) {
       Connection conn = null;
       PreparedStatement st = null;
       ResultSet rs = null;

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

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

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

           //业务完毕,提交事务
           conn.commit();
           System.out.println("成功");
       } catch (SQLException e) {
           try {
               conn.rollback();//如果失败,则回滚事务 。不写也会默认回滚
           } catch (SQLException ex) {
               ex.printStackTrace();
           }
           e.printStackTrace();
       } finally {
           JdbcUtils.release(conn,st,rs);
       }

   }
   }

失败情况

package lesson04;

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

/**

 * @Auther: fei

 * @Date: 2021/7/3 - 07 - 03 - 15:28

 * @Description: lesson04

 * @version: 1.0
   */
   public class TestTransation02 {
   //这是一个main方法,是程序的入口:
   public static void main(String[] args) {
       Connection conn = null;
       PreparedStatement st = null;
       ResultSet rs = null;

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

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

           int x = 1/0; //报错

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

           //业务完毕,提交事务
           conn.commit();
           System.out.println("成功");
       } catch (SQLException e) {
           try {
               conn.rollback();//如果失败,则回滚事务
           } catch (SQLException ex) {
               ex.printStackTrace();
           }
           e.printStackTrace();
       } finally {
           JdbcUtils.release(conn,st,rs);
       }

   }
   }

10.8 数据库连接池

数据库连接-执行完毕-释放 连接-释放 ,十分浪费系统资源

池化技术

准备一些预先的资源,过来就连接预先准备好的 - -开门-业务员:等待-服务— 常用连接数:10 最小连接数:10 最大连接数:15,业务最高承载上限 排队等待 等待超时:100ms 编写连接池,实现一个接口DataSource

开源数据源实现

DBCP C3P0 Druid :阿里巴巴 使用了这些数据库连接池之后 ,我们在项目开发过程中就不需要编写连接数据库的代码了!

DBCP

需要用到的jar包 Commons-dbcp-1.4.jar Commons-pool-1.6.jar 写配置文件 Dbcpconfig.properties

#连接设置

driverClassName=com.mysql.jdbc.Driver

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

username=root

password= ***

#初始化连接

initalSize=10

#最大连接数量

maxActive=50

#<!-- 最大空闲连接>

maxIdle=20


# 最小空闲连接

minIdle=5

#超时等待,60s

maxWait=60000

\#JDBC驱动建立连接,users和password会被明确传递,可以不包含

connectionProperties=useUnciode=**true**;characterEncoding=UTF8

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

defaultAutoCommit=**true**

\#deiver **default**,指定只读状态

defaultReadOnly=

\#deiver **default**,指定事务级别

defaultTransactionIsolation=READ_UNCOMMITTED

写配置代码

package lesson05;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import utils.JdbcUtils;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**

 * @Auther: fei

 * @Date: 2021/7/3 - 07 - 03 - 16:16

 * @Description: lesson05

 * @version: 1.0
   */
   public class JdbcUtils_DBCP {
   private static DataSource dataSource = null;

   static {
       try {
           InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
           Properties properties = new Properties();
           properties.load(in);
           //创建数据源,工厂模式-创建
           dataSource = BasicDataSourceFactory.createDataSource(properties);
       } catch (Exception e) {
           e.printStackTrace();
       }
   }

   //获取连接
   public static Connection getConnection() throws SQLException {
       return dataSource.getConnection(); //从数据源中获取连接
   }

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


       if (st != null) {
           try {
               st.close();
           } catch (SQLException e) {
               e.printStackTrace();
           }
       }

       if (conn != null) {
           try {
               conn.close();
           } catch (SQLException e) {
               e.printStackTrace();
           }
       }

   }
   }

测试DBCP代码

package lesson05;

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

/**

 * @Auther: fei

 * @Date: 2021/7/3 - 07 - 03 - 16:24

 * @Description: lesson05

 * @version: 1.0
   */
   public class TestDBCP {
   public static void main(String[] args) {
       Connection conn = null;
       PreparedStatement st = null;


       try {
           conn = JdbcUtils_DBCP.getConnection();
           //区别
           //使用?点位符代替参数
           String sql = "insert into users(id,`name`,`password`,`email`,`birthday`)" +
                       "values(?,?,?,?,?)";
           st = conn.prepareStatement(sql);//预编译sql,先写sql,但不执行

           //手动赋参数
           st.setInt(1,4);
           st.setString(2,"xiao");
           st.setString(3,"123123");
           st.setString(4,"4***@qq.com");

           //注意点,sql.Date,数据库
           //util.Date,Java,获得时间戳
           //new java.sql.Date(new java.util.Date().getTime())
           st.setDate(5, new java.sql.Date(new java.util.Date().getTime()));

           //执行
           int i = st.executeUpdate();
           if(i>0){
               System.out.println("插入成功!");
           }
       } catch (SQLException e) {
           e.printStackTrace();
       } finally {
           JdbcUtils_DBCP.release(conn,st,null);
       }

   }
   }

C3P0

需要用到的jar包 C3P0-0.9.5.5.jar mchange-commons-java-0.2.19.jar

结论

无论使用什么数据源,本质还是一样的,DataSource接口不变,方法就不会变