MYSQL基本操作
一、数据库简介
1.1 简介
数据库(Data Base,简称DB):长期保存在计算机的存储设备上,数据按照一定的规则组织起来,可以被各种用户、应用共享的数据集合。
数据库管理系统(Database Management System, 简称DBMS):指的是一种用来管理和操作数据的大型软件,用于建立、使用、维护数据,对数据库进行统一的管理和控制,以保证数据的完整性和安全性。用户可以通过数据库管理系统访问数据库中的数据。
数据库:存储、维护和管理数据的集合。
数据库管理系统:数据库软件,数据库是通过这些软件进行创建和操作的。
1.2 常见的数据库管理系统
- Oracle:被认为是目前业界比较成功的关系型数据库的管理系统。Oracle可以运行在Windows、UNIX等主流的操作系统平台,完全支持所有的工业标准,并获得了最高级别的ISO标准安全性认证。
- MySQL:是一种关系型数据库管理系统。由瑞典MySQL AB公司开发,目前属于Oracle旗下产品。MySQL是目前最流行的关系型数据库管理系统(RDBMS:Relational DBMS)之一。
- SQLServer:是由微软推出的关系型数据库管理系统。
- DB2:是IBM的
1.3 关系型数据库、非关系型数据库
- 非关系型数据库:
- 采用了没有特定关系模型来组织数据。
- NOSQL基于键值对
- 关系型数据库:
- 依据所有存储数据的模型之间的关系建立的数据库。
- 所谓关系模型,指的是“一对一、一对多、多对多”等关系模型
二、MySQL的安装与卸载
2.1 安装
如果在安装的过程中缺少依赖:https://www.microsoft.com/zh-cn/download/details.aspx?id=40784
2.2 卸载
- 控制面板 -> 程序 -> 卸载程序 -> 找到MySQLServer -> 右键 -> 卸载
- 打开C盘 -> 打开ProgramData文件夹 -> 删除MySQL文件夹
- 清除注册表信息:
- 打开注册表:win+r 输入:regedit
- HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\EventLog\Application\MySQL
- HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services\EventLog\Application\MySQL
- HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\MySQL
2.3 启动、停止MySQL服务
-
以管理员的身份运行命令行
-
开始菜单 -> windows系统 -> 命令提示符 -> 右键 -> 以管理员身份运行
-
输入指令:
net start mysql57 // 开启服务 net stop mysql57 // 停止服务
-
2.4 登录到数据库
-
打开命令行
-
输入指令:
如果输入mysql提示“不是内部命令,也不是外部命令”,说明需要配置环境变量:
- 此电脑 -> 右键 -> 属性 -> 高级系统设置 -> 环境变量 -> 系统变量 -> Path
- 将MySQLServer安装路径下的bin配置进来
- C:\Program Files\MySQL\MySQLServer 5.7\bin
1. mysql -u root -p // 这种方式的登录,敲回车后需要输入密码 2. mysql -uroot -p123456 // 将用户名和密码都写到指令中,注意:没有空格
SQL语言
SQL简介
SQL: Structure Query Language(结构化查询语言),SQL最早是被美国国家标准局(ANSI)确定为关系型数据库语言的美国标准。后来被国际化标准组织(ISO)采纳为关系型数据库语言的国际标准。
各种数据库厂商都支持ISO标准的SQL,类似于普通话。
各个数据库厂商在标准的基础上,定义了若干自己的扩展,类似于方言。
SQL是一种标准化的语言,允许你在数据库上进行操作,如:创建项目、查询内容、更新内容和删除内容等操作。
这些操作:Create、Read、Update、Delete,通常被称为 CRUD操作
1.SQL分类
- DDL(Data Definition Language):数据定义语言,用来定义数据库对象(数据库、表、列)
- DML(Data Manipulation Language):数据操作语言,用于定义数据库记录(数据)
- DCL(Data Control Language):数据控制语言,用于定义访问权限和安全级别
- DQL(Data Query Language):数据查询语言,用于查询记录(数据)
SQL语句大小写是不区分的。
CREATE / create / Create / CrEaTe
但是,一般情况下,我们会大写。
2.DDL使用(数据库)
-
创建数据库
# 创建数据库 CREATE DATABASE mydb1; # 创建数据库,并采用指定的字符集 CREATE DATABASE mydb2 CHARACTER SET UTF8;
-
查看数据库
# 查看当前数据库服务器中的所有的数据库 SHOW DATABASES; # 查看创建数据库mydb1定义的信息 SHOW CREATE DATABASE mydb1;
-
修改数据库
# 将数据库mydb1的字符集修改为GBK ALTER DATABASE mydb1 CHARACTER SET GBK;
-
删除数据库
DROP DATABASE mydb1;
-
其他操作
# 切换当前使用的数据库 USE mydb1; # 查询当前使用的数据库 SELECT DATABASE();
3. DDL使用(表)
表:数据在数据库中的存储是以表的形式存在的。一个表中有若干个字段,将数据按照这些字段进行存储。
每一个字段在设计表的时候都要去指定类型:
int:整型
double:浮点型,例如double(5,2):表示最多有5位,其中必须有两位是小数,即最大值是 999.99
char:固定长度的字符串,例如char(5) : ‘aa’ 占5位
varchar:可变长度的字符串,例如varchar(5):‘aa’ 占2位
text:字符串类型
blob:字节类型
date:日期类型,格式是:yyyy-MM-dd
time:时间类型,格式为:hh:mm:ss
timestamp:时间戳类型,yyyy-MM-dd hh:mm:ss,会自动赋值
datetime:时间类型,yyyy-MM-dd hh:mm:ss
# DDL操作(表)
# 创建表格
CREATE TABLE t_users(name varchar(50), age INT, gender VARCHAR(10), height INT, weight INT);
# 删除表格
DROP TABLE t_users;
# 查看当前数据库中所有的表
SHOW TABLES;
# 查看创建一个表的信息
SHOW CREATE TABLE t_users;
# 查看一张表的字段信息
DESC t_users;
# 给一张表添加一个字段
ALTER TABLE t_users ADD score DOUBLE(5,2);
# 修改一张表的字段类型
ALTER TABLE t_users MODIFY score INT;
# 修改一张表的字段名
ALTER TABLE t_users CHANGE name uname VARCHAR(50);
# 修改一张表的字符集
ALTER TABLE t_users CHARA CTER SET GBK;
#修改表的名字
RENAME TABLE t_users TO t_new_user;
# 删除一张表中的字段
ALTER TABLE t_users DROP score;
4. DML
DML指的是对数据库中的数据进行增、删、改的操作。不要和DDL搞混了。
在SQL中,字符串类型和日期类型需要用单引号括起来
空值:null / NULL
1.插入数据
# 增:INSERT INTO
# 向表t_users插入一条数据,并且给每一个字段进行赋值,小括号中的是字段对应的值。要保证顺序。
INSERT INTO t_users VALUES('lily', 21, 'female', 172, 60);
INSERT INTO t_users VALUES('lucy', 21, 'female', 171, 60);
# 向表t_users插入一条数据,并且对部分字段进行赋值
INSERT INTO t_users (uname, age, gender) VALUES('JimGreen', 22, 'male');
# 向表t_users插入一条数据,并且对部分字段进行赋值,字段的顺序可以随意,但是要保证values后面的值要和前面的字段匹配
INSERT INTO t_users (age, gender, uname) VALUES(10, 'male', 'polly');
2.where
在进行数据删除、修改、查询的时候,可以使用where对数据进行一个过度。
= :相等比较(类似于Java中的==)
!= <> :表示不相等
< > >= <= :大小比较
BETWEN…AND…:在xxx和xxx之间
IN(set):在括号所有值之间取 /NOT IN
IS NULL /IS NOT NULL
AND、OR、NOT
3、删除数据
# 删除数据
DELETE FROM t_student;
# 按照条件进行删除 WHERE
DELETE FROM t_student WHERE sname = '韦一笑';
# 删除掉表中所有的数据(创建了一个新表)
TRUNCATE TABLE t_student;
DELETE 和 TRUNCATE
- delete删除表中的数据,表结构还在;删除的数据可以恢复。
- truncate是直接将表DROP掉,然后再按照原来的结构重新创建一张表。数据不可恢复。
- truncate删除效率比delete高。
4、修改数据
UPDATE 表 set 字段=xx where
DQL数据查询
DQL:数据库在执行DQL操作的时候,不会对数据造成修改。而是直接将查询后的结果集返回给客户端。查询的结果是一张虚拟的表。
关键字:SELECT
注意:在执行SQL的时候,后面可能跟上很多的限定。这些限定的顺序:
子句执行顺序
from -> where -> group by -> having -> select -> order by
据此: 所以需要注意 as 别名的使用位置,不能先使用后声明
1 基础查询
# * :所有列
select * from *
2 模糊查询
# '_':通配符,表示一位
# '%':通配符,表示若干位
# 关键字:LIKE
3 字段控制查询
1.去重,去除重复记录,关键字:DISTINCT
# 去除两个列都相同的字段
select distinct xx,yy from
2.常见计算
#只有数值类型可以做相加
#NULL值和其他数值做运算,结果还是NULL
#IFNULL(colum,defaultValue)
#如果指定的Colum列的值是NULL,则按照defaultValue进行计算处理
3.列别名 AS
AS 是可以省略的
4.查询结果排序 ORDER BY
# 查询结果排序
# ASC 升序(可以省略的)
# DESC 降序
# 默认是按照升序排序的
# 查询结果按照score_java做降序,如果score_java相同,再按照score_hadoop做升序
SELECT sname, score_java, score_hadoop FROM t_student ORDER BY score_java DESC, score_hadoop ASC;
5.聚合函数
聚合函数的特点
1.每个组函数接收一个参数(字段名或者表达式) 统计结果中默认忽略字段为NULL的记录
2.要想列值为NULL的行也参与组函数的计算,必须使用IFNULL函数对NULL值做转换。
3.不允许出现嵌套 比如sum(max(xx))
聚合函数无法用在where子句中 , 聚合函数包括
count avg sum min max
# 聚合函数是用来做纵向计算的函数
# COUNT():统计个数
# COUNT(xx or null): 不会统计NULL值(其余都会+1)
# MAX():求最大值
# MIN():求最小值
# AVG():求平均值
# SUM():求和
6.分组 GROUP BY
# HAVING:对数据做一个简单的约束(限制),类似于where
# 查询Java平均成绩 > 75 的组号和平均成绩
SELECT groupid, AVG(score_java) FROM t_student GROUP BY groupid HAVING AVG(score_java) > 75;
HAVING 和 WHERE的区别:
HAVING后面可以写聚合函数、WHERE后面是不可以写聚合函数的。
HAVNIG是对分组后的数据做的过滤、WHERE是对分组前的数据做的过滤。
- WHERE对分组前的数据做过滤。如果没有满足WHERE条件过滤的数据,将不参加分组。
- HAVING是分组后的数据做过滤。
7.分页 LIMIT
分页可以分为:假分页(逻辑分页)、真分页(物理分页)
- 假分页:
- 可以将表中的数据一次性全部读取出来,存到一个集合中。可以自己设计程序,每次从这个集合中取指定部分的元素。
- 优点:效率高
- 缺点:如果表中的数据量过大,可能会造成内存溢出
- 真分页:
- 每次从表中查询指定数量的数据。
LIMIT 0, 1000:
# 第一个参数0: 从哪一条数据开始查询
# 第二个参数1000: 每次查询多少数据(相当于一个分页中有多少数据)
数据的完整性
在创建表的时候对某些字段进行约束,确保数据的完整性。
保证用户输入的数据添加到数据库中的时候是正确的。
- 实体完整性
- 域完整性
- 引用完整性
1 实体完整性
实体:表中的每一行数据,代表一个实体(Entity)
实体完整性:标识每一行数据不重复。
约束:
主键约束(primary key)
唯一约束(unique)
自增约束(auto_increment)
主键约束
主键:可以将表中的某些键设置为主键。
特点:不允许重复,且不能是NULL值。
用途:可以使用主键,作为一个实体(一条数据)的唯一标识。
一般情况下,一张表中是需要有主键的。主键的数量:如果没有什么特殊需求,一个就可以。
# 设置主键
# 1. 在建表的时候,设置某一个键为主键
CREATE TABLE t_class (
id int PRIMARY KEY,
cname VARCHAR(20)
);
CREATE TABLE t_class(
id INT,
cname VARCHAR(20),
PRIMARY KEY(id,cname)
);
# 2. 给一个已经创建好的表添加主键(这个键是一个已经存在的键)
ALTER TABLE t_class ADD PRIMARY KEY(id);
唯一约束
数据不允许重复,但是可以是NULL
在创建表的时候,用关键字 UNIQUE 来修饰
# 设置唯一约束unique
CREATE TABLE t_class(
id INT PRIMARY KEY,
cname VARCHAR(20) UNIQUE
);
自增约束
自动增长 AUTO_INCREMENT
*如果使用auto_increment设置自增字段,没有与主键约束一同使用,则使用auto_increment的字段必须添加索引,否则创建数据表会出错*
CREATE TABLE t_class(
id INT PRIMARY KEY AUTO_INCREMENT,
);
2 域完整性
限制单元格内容的正确性
数据类型、非空约束、默认值约束
非空约束
NOT NULL
CREATE TABLE t_teacher(
gender VARCHAR(10) NOT NULL
);
默认值约束
修饰某一个字段的值有一个默认值
# 默认值约束
CREATE TABLE t_teacher(
gender VARCHAR(10) DEFAULT 'male'
);
CREATE TABLE t_teacher(
gender VARCHAR(10) NOT NULL DEFAULT 'male'
);
3 引用完整性
参考完整性
将多一方(student)表中的用来维系关系的键,作为外键(forigen key)
外键约束:FOREIGN KEY
约束外键列的值,只能在另外的一张关联的表中进行设置
设置外键约束需要注意:
查看一张表的存储引擎,如果希望某张表支持外键,则需要将存储引擎设置为 InnoDB
MyISAM: 也是一种存储引擎,采用这种存储引擎的表,存取效率高,但是不支持事物和外键
ALTER TABLE 表名 ENGINE = 'InnoDB';
SQL 添加外键
# 设计一个表,并设置一个外键
# 外键:class_id
# 关联表:t_class
# 关联字段:id
CREATE TABLE t_stu(
id INT PRIMARY KEY,
class_id INT, # 外键的类型一定要和关联表中的关联字段类型相同
CONSTRAINT fk_class_id FOREIGN KEY(class_id) REFERENCES t_class(id)
);
# 给一个已经创建好的表添加外键
ALTER TABLE t_stu ADD CONSTRAINT fk_class_id FOREIGN KEY(class_id) REFERENCES t_class(id);
多表查询
联合多个表中的数据进行数据查询。
1 多表的关系
-
一对一
在实际开发中应用不多。因为一对一的关系,完全可以放到一个表中
-
一对多
一对多建表原则:在多的一方,创建一个字段,作为外键作为指向另外一的那一方的主键。
-
多对多
多对多的建表原则:需要创建第三张表,在中间表中至少需要有两个字段。这两个字段分别作为外键指向各自一方的主键。
2 多表查询
-
合并查询结果集
作用:合并结果集就是把两个select到的结果集合并到一起
注意事项:需要合并的两个结果集要求:列数和类型必须相同
- UNION:合并结果集,去重。
- UNION ALL:合并结果集,不去重。
SELECT * FROM t_union_user1 UNION SELECT * FROM t_union_user2; SELECT * FROM t_union_user1 UNION ALL SELECT * FROM t_union_user2;
-
连接查询
连接查询,就是求出多个表的乘积,例如 t1连接t2表,查询结果就是t1 * t2
连接查询,一般情况下要查询的两张表之间是需要有关联的。
连接查询会出现笛卡尔积:
假设有两个 集合A{a, b} 和 集合B {0, 1, 2},
这两个集合的笛卡尔积是 {(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}
这样的话,这个查询结果很多的数据都不是我们想要的。所以我们要去除重复的或者无用的数据。通过条件过滤。
-
内连接
查询两张表中都出现的数据(外键)
-
外连接
特点:可能会出现不满足条件的数据
-
左外连接
先查询出左表,再查询右表,将满足条件的数据列出,同时再列出左表中不满足条件的数据。
-
右外连接
先查询出右表,再查询左表,将满足条件的数据列出,同时再列出右表中不满足条件的数据。
-
-
# 连接查询
# 查询两张表中所有的数据
# 这种查询就是一个内连接(但是这种语法是MySQL单独为自己设计的语法,方言)
SELECT * FROM t_student, t_class WHERE t_student.cid = t_class.id;
SELECT sname, t_student.sage, t_student.sgender, t_class.cname FROM t_student, t_class WHERE t_student.cid = t_class.id;
# 内连接标准SQL
# INNER可以省略
SELECT * FROM t_student INNER JOIN t_class ON t_student.cid = t_class.id;
SELECT * FROM t_student JOIN t_class ON t_student.cid = t_class.id;
SELECT *
FROM t_student stu
JOIN t_class cls
ON stu.cid = cls.id
where stu.xxx= cls.xxx;
# 外连接
# OUTER 也可以省略
SELECT *
FROM t_student stu
LEFT OUTER JOIN t_class cls
ON stu.cid = cls.id;
SELECT *
FROM t_student stu
RIGHT JOIN t_class cls
ON stu.cid = cls.id;
子查询
子查询就是一个嵌套查询。就是一个SELECT语句中嵌套另外一个SELECT。
select xxx from xxx where xxx 关系运算 (select xxx from xxx )
CASE-WHEN
可以做一些简单的分支逻辑,类似于if-else和switch-case
select xxx,
CASE #相当于if
WHEN xxxx
THEN xxx
END AS xxx
from xxx
select xxx,
CASE xxxx #相当于switch
WHEN 1 THEN xxx
END AS xxx
from xxx
# 行转列
# group by 只取分组后的第一条数据展示
# 先执行group by 再执行聚合函数
# 分组函数一定和聚合函数一同存在
SELECT sname,
SUM(CASE subject WHEN '语文' THEN score ELSE 0 END) AS '语文成绩',
SUM(CASE subject WHEN '数学' THEN score ELSE 0 END) AS '数学成绩',
FROM t_scores GROUP BY sname;
SELECT sname,
SUM(IF(subject = '语文', score, 0)) AS '语文成绩',
SUM(IF(subject = '数学', score, 0)) AS '数学成绩',
FROM t_scores GROUP BY sname;
JDBC
第一个JDBC程序
JDBC:Java Database Connectivity
JAVA中的数据库连接,是用来连接各种数据库的中间件。
由于市面上的数据库管理系统(DBMS)种类繁多,如果我们的程序需要和多种数据库进行交互,则需要设计多套逻辑来进行处理。这多套逻辑之间有很大一部分是重叠的,而且还需要针对不同的数据库进行分别处理。程序设计就会很繁琐。于是JDBC就诞生了。
JDBC是一套访问数据库规范,让不同的数据库厂商去实现这些规范即可。对于我们写程序来说,就不用再针对不同的数据库进行区分处理,直接使用JDBC的API即可。
1 使用JDBC的基本步骤
- 注册驱动
- 建立连接
- 创建Statement
- 执行SQL,得到结果集
- 处理结果集中的数据
- 释放资源
2 通用JDBC组件
- DriverManager:用来管理数据库驱动程序列表。
- Driver:驱动对象。
- Connection:程序与数据库的连接对象。
- Statement:用来执行SQL语句。
- ResultSet:SQL执行结束后的结果集。
- SQLException:在执行数据库操作的过程中遇到的异常。
3 第一个JDBC程序
创建项目,导入jar包,在jar包上右键,BuildPath -> Add to BuildPath
注册驱动
// 1. 注册驱动
// registerDriver方法的参数是一个java.sql.Driver接口,所以我们要传一个实现类对象
// com.mysql.jdbc.Driver这个类对象才是我们需要的参数
// DriverManager.registerDriver(new com.mysql.jdbc.Driver);
// 因为在com.mysql.jdbc.Driver类中的静态代码段中已经实现了注册,所以我们不需要重复注册
// 只需要去触发静态代码段即可
Class.forName("com.mysql.jdbc.Driver");
建立连接
// 2. 建立连接
// url: 连接到指定的数据库路径
// jdbc:mysql://主机名(数据库所在的机器IP,名字):端口号/数据库名字
// user: 登录用户名
// password: 密码
// Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/数据库名", "root", "123456");
// 将数据库路径与用户名、密码都封装到一个url中
String url="jdbc:mysql://localhost:3306/数据库名?user=用户名&password=密码"
conn = DriverManager.getConnection(url);
创建Statement对象
//静态SQL的语句
Statement st=coon.createStatement();
执行SQL,得到结果
// 4. 执行SQL语句
// executeUpdate(String sql): 执行一个DDL、DML语句,并返回这个操作影响的行数 int
// executeQuery(String sql): 执行一个DQL语句,并返回一个ResultSet
处理结果集中的数据
// 5. 处理这些数据
while (set.next()) {//一条条查询,没有数据就返回false
//得到的结果可以用列序号获取,也可以用列名(字段名)来获取
//返回的数据对类型没有强制要求
int id = set.getInt(1);
String name = set.getString("sname");
}
释放资源
// 6. 释放资源
// 需要释放的资源有:ResultSet、Statement、Connection
//按ResultSet、Statement、Connection 的顺序依次释放
set.close();
st.close();
conn.close();
DAO层设计
程序设计最基本原则:
1.可复用性。减少程序中的重复代码。
2.可扩展性。当需要添加功能的时候,只需要在现有的架构上添加模块即可,不需要对现有的代码进行改动
3.可维护性。当需求变更的时候,能够用最少的改动实现效果。
高内聚,低耦合
DAO:数据访问模型(Data Access Object),用来访问数据库的。用来数据库中的数据存取。
DAO包的设计:
设计规范:
DAO包是由DAO接口和DAO 实现类和描述类组成(开发中还有一个测试类)
命名规范:
公司域名倒写.项目名称.DAO:主包
.domain 存放描述类
.dao dao接口
.dao.imp dao实现类
.dao.test 测试类
关于dao接口命名规范:
- I开头,以DAO做结尾
- 中间写domain描述类
优化
使用 properties
private static Properties pro = new Properties();
// 使用ClassLoader来加载一个Properties里面的数据
// 1. 创建ClassLoader对象
ClassLoader loader = Thread.currentThread().getContextClassLoader();
// 2. 获取用于操作某个文件的字节流对象
InputStream in = loader.getResourceAsStream("db.properties");
// 3. 加载数据
pro.load(in);
Class.forName(pro.getProperty("driverName"));
预编译语句 PreparedStatement:
优点:
- 使用预编译语句,可以提高代码的可读性。
- 最大的好处:还可以提高性能!(预编译)
- MYSQL不支持!Oracle是支持的!
- 保证安全
// 提供一个“模板”, 用?做占位, 在实际使用的时候, 需要先对占位的部分进行赋值。
PreparedStatement ps = conn.prepareStatement(sql);
// 给占位赋值(注意类型)
ps.setInt(1, 10);
ps.setString(2, "Uncle wang");
ps.setString(3, "男");
ps.close();
批处理操作
可以将多条SQL语句分组到一个批处理中,同时去执行这多条SQL。
-
获取Statement对象
-
将自动提交关闭
conn.setAutoCommit(false);
-
使用addBatch()方法将需要执行的SQL添加进来
st.addBatch("insert into t_teacher values (3, '郭靖', '男')");
-
使用executeBatch()处理所有的SQL
int[] rows = st.executeBatch();
-
最后使用commit()方法进行提交
conn.commit();
事务
是数据库操作的一个执行单元。一组要么同时执行成功,要么同时执行失败的SQL语句。
1 事务的特点(ACID)
- atomtity(原子性)
- 表示一个事务内的所有操作是一个整体。要么全部成功,要么全部失败。
- consistency(一致性)
- 表示一个事务中有一个操作失败,所有更改过的操作都必须回滚到操作之前的状态。
- isolatioin(隔离性)
- 事务在查看数据的状态。要么查询到的是一个事务执行之前的状态,要么是一个事务执行之后的状态。不会查询到一个事务执行过程中的状态。
- durability(持久性)
- 持久性事务执行完成后,对系统的影响是持久的。
2 事务的隔离级别
SQL 定义了四类标准的隔离级别
- 读取未提交内容(Read Uncommitted):
- 在开发中使用的极少。读取未提交的内容:脏读(Dirty Read)
- 读取提交内容(Read Committed):
- 绝大部分的数据库的默认的隔离级别。(MySQL不是)。一个事务只能看到已提交的事务所做的改动。
- 可重复读(Repeatable Read)
- 是MySQL默认的隔离级别
- 可串行化(Serializable)
3 Java中的事务
首先需要将Connection的自动提交功能关闭
Savepoints:保存点
Connection:
setSavepoint(String savePointName):定义一个保存点,并设置一个名字,返回一个Savepoint对象
releaseSavepoint(Savepoint savePointName):删除一个保存点
事务开始于:
- 连接到指定的数据库,并执行一条DML语句(insert、update、delete)
- 前一个事务已经结束,此时又执行一条DML语句
事务结束于:
- 执行
commit
或者rollback
语句 - 执行一条DDL语句,例如:建表。此时会自动执行一个
commit
- 断开与数据库的连接
连接池
去操作数据库的时候,我们使用到一个Connection对象,如果使用传统的JDBC操作方式,每次进行操作的时候都需要创建一个新的连接,创建Connection的过程,非常消耗性能和时间的过程,所以会带来不必要的性能损耗和时间损耗。为了解决这个问题,我们引入一个”池子“的概念。如果需要Connection对象的时候,直接从这个池子中去获取。当不用这个Connection的时候,不是将其释放,而是放到池子中,等待下次继续使用。实现一个Connection对象的复用。
1 自定义连接池
属性:集合,存储Connection对象
方法:获取连接对象、
// 1. 判断复用池中有没有Connection对象 if (list.size() > 0) { // 2. 说明此时连接池中是有Connection对象 // 3. 从池子中取出一个对象返回即可 return list.removeFirst(); } // 如果此时池子中没有连接对象 // 理论上需要做一个等待时间:在等待时间内,如果有Connection归还,可以直接获取。如果等待超时,则直接创建一个新的Connection对象返回 // 不去模拟等待时长,直接返回一个新的 return JDBCUtil.getConnection();
归还连接对象
// 1. 判断池子的容量是不是达到了最大值 if (list.size() >= capcity) { // 说明池子已经存满了,这个conn直接释放即可,不用添加到池子中 try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } else { // 说明复用池还不满,此时将归还的conn添加到集合中即可 list.add(conn); }
2 DBCP
Database Connection Pool(数据库连接池),是apache上的一个Java连接池项目。
// 1. 实例化一个连接池对象
BasicDataSource ds = new BasicDataSource();
// 2. 设置连接信息
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/mydb1");
ds.setUsername("root");
ds.setPassword("123456");
// 设置最大连接数
ds.setMaxActive(20);
// 3. 获取连接
Connection conn = ds.getConnection();
// 在ds.getConnection()方法中返回的是一个DBCP中已经做好的Connection接口的实现类对象
// 在这个Connection接口的实现类中,已经对close做了一个复用的操作。
conn.close();
DataSource: 是一个接口,定义了几个用来做连接池的规范
需要使用到jar包:
- jdbc.jar
- commans-dbcp.jar
- commans-pool.jar
3 c3p0
C3P0是一个开源的JDBC连接池。
和DBCP的区别:
DBCP没有自动回收空闲连接的功能,C3P0有这个功能。
DBCP不需要手动设置配置文件,C3P0需要手动设置配置文件。(source 下创建 c3p0-config.xml文件)
<!-- C3P0中,关于数据库连接的配置 --> <!-- driverClass: 驱动类名 jdbcUrl: 数据库路径 user: 用户名 password: 密码 initialPoolSize : 实例化的时候连接池中的连接数量 maxPoolSize : 最大连接数量 --> <c3p0-config> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb1</property> <property name="user">root</property> <property name="password">123456</property> <property name="initialPoolSize">10</property> </default-config> </c3p0-config>
ComboPooledDataSource ds = new ComboPooledDataSource();
// 获取连接
Connection conn = ds.getConnection();
Statement st = conn.createStatement();
需要使用到jar包:
- jdbc.jar
- c3p0.jar
关于配置文件:
- 是一个xml文件:c3p0-config.xml
- 这个文件需要放到source下面
4 Druid(阿里巴巴)
使用比较流行的。
DruidDataSource ds = new DruidDataSource();
需要使用到jar包:
- jdbc.jar
- druid.jar
DBUtils
是apache上的一个开源项目,是对JDBC进行了一个简单的封装。可以使用这个工具类来用简洁的代码实现数据库的操作,并且不影响性能。
需要类库:
- jdbc.jar
- dbutils.jar
- c3p0.jar
//通过创建C3P0Utils获取一个DataSource连接池
//ds=C3P0Utils.getDataSource()
QueryRunner runner = new QueryRunner(DataSource ds);
// 指定查询语句的时候:
runner.query(String sql, ResultSetHandler handler);
// ResultSetHandler:
// org.apache.commons.dbutils.handlers;
// BeanHandler: 将ResultSet中的第一行数据转成一个数据模型(类的对象)
// BeanListHandler: 将ResultSet中的所有的数据每一行都转成一个数据模型,然后存入一个集合中。
// ArrayHandler: 将ResultSet中的第一行数据转成一个对象数组
// ArrayListHandler: 将ResultSet中的所有的数据每一行都转成一个对象数组,然后存入一个集合中。
// MapHandler :将ResultSet中第一行的数据存成Map映射
// MapListHandler :将ResultSet中所有的数据存成List。List中存放的是Map