控制台操作数据库
mysql -u 账号 -p 密码 --连接数据库
-------------------------------
进入mysql>之后所有的语句都要以;结尾
--sql单行注释
/*
sql多行注释
*/
update mysql.user set authentication_string=password('123456')
where user='root' and Host='localhost'; --修改用户密码
show databases; --查看所有的数据库
use 数据库名; --切换数据库
show tables; --查看数据库中所有表
describe 表名; --查看表中的所有数据
create database 数据库名; --创建数据库
exit; --退出连接
1. 数据库语句(创库,创表,创约束,修改表)
所有的创建和删除操作都尽量加上判断
删除有外键关系的表时,必须要先删除应用别人的表(从表),再删除被引用的表(主表)
if not exists 如果不存在
if exists 如果存在
创建数据库
create database if not exists 数据库名;
删除数据库
drop database if exists 数据库名;
查看创建数据库的语句
show create database 数据库名
查看创建表的语句
show create table 表名
删除表
DROP TABLE IF EXISTS student
显示表的结构
desc 表名
----------------------------------------------------------------
--表名称和字段最好用``括起来,所有的字符串都使用''单引号括起来
--每个字段创建的最后都要加逗号, 最后结束的字段不需要加逗号
--not null=不能为空,auto_increment=自增,comment('')=给字段取注释
--主键写在最后,primary key(`id`)
--default charset=utf-8,改变默认编码格式
--ENGINE=innodb 表引擎
/*innodb安全性高,支持事务的处理,多表多用户操作
myisam节约空间,速度较快*/
创建表
CREATE TABLE IF NOT EXISTS `student` (
`id` INT(3) AUTO_INCREMENT NOT NULL COMMENT'学号',
`name` VARCHAR(30) 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'家庭住址',
`emall` VARCHAR(50) DEFAULT NULL COMMENT'邮箱',
PRIMARY KEY(id)
)ENGINE=INNODB DEFAULT CHARSET=utf8
----------------------------------------------------------------
修改表(所有跟表有关的修改都用alter)
--修改表名,关键词 rename
ALTER TABLE 旧表名 RENAME AS 新表名
--增加表字段,关键词 ADD
ALTER TABLE student ADD age INT(3) DEFAULT NULL COMMENT '年龄'
--修改表字段类型和约束,关键词modify(只能修改表字段的类型和约束)
ALTER TABLE student MODIFY age INT(5)
--修改表字段名和表字段的类型与约束,关键词change(可以同时修改字段名和字段的类型与约束)
--数据类型一定要一致才可以改名
ALTER TABLE student CHANGE age age1 INT(5)
--删除表字段,关键词 drop
ALTER TABLE student DROP age
--物理外键,不建议使用
--创建表的外键约束,constraint 创建什么约束,foreign key 跟什么外交,references 涉及到哪个表的那个字段
ALTER TABLE student
ADD CONSTRAINT `FK_gradeid`
FOREIGN KEY(`gradeid`)
REFERENCES `grade`(`gradeid`)
2. 数据库的数据类型
2.1 数值
- tinyint 十分小的数据 1个字节
- smallint 较小的数据 2个字节
- mediumint 中等大小的数据 3个字节
- int 标准的整数 4个字节(常用)
- bigint 较大的数据 8个字节
- float 浮点数 4个字节
- double 浮点数 8个字节
- decimal 字符串形式的浮点数 金融计算的时候使用
2.2 字符串
-
char 固定大小的字符串 0~255
-
varchar 可变字符串 0~65535 (常用)
-
tinytext 微型文本 2^8 - 1
-
text 文本串 2^16 - 1
2.3 时间日期
- date YYYY-MM-DD 日期格式
- time HH:mm:ss 时间格式
- datetime YYYY-MM-DD HH:mm:ss 最常用的时间格式 (常用)
- timestamp 1970.1.1到现在的毫秒数 时间戳 (常用)
- year 年份表示
3. 数据库的字段属性
unsigned:
- 无符号的整数
- 声明了该列不能为负数
zerofill:
- 0填充
- 不足的位数,使用0来填充,如:int(3), 5=005
自增:
-
自动在上一条记录的基础上+1
-
通常用来设计唯一的主键,必须是整数类型
-
可以自定义设计主键自增的起始值和步长
非空:
-
设置为not null,如果不给他赋值,就会报错
-
不填写值,默认值就是null
默认:
- 设置默认值
- 比如sex,默认值为男
拓展:
/*每一个表都必须存在以下五个字段,阿里巴巴规范
id 主键
`version` 乐观锁
is_delete 伪删除
gmt_create 创建时间
gmt_update 修改时间
*/
4. 判断操作符
操作符 | 含义 | 范围 | 结果 |
---|---|---|---|
= | 等于 | 1=1 | true |
<>或!= | 不等于 | 1<>2 | true |
> | 大于 | 2>1 | true |
< | 小于 | 1<2 | true |
>= | 大于等于 | 2>=2 | true |
<= | 小于等于 | 2<=2 | true |
between … and … | 区间 | id between 1 and 5 | id为1-5之间的值 |
and | 跟java中的&&一样 | 2>1 and 3>2 | true |
or | 跟java中的||一样 | 1>2 and 2>1 | true |
5. 比较运算符(模糊查询)
运算符 | 语法 | 描述 |
---|---|---|
is null | a is null | 如果操作符为null,true |
is not null | a is not null | 如果操作符不为null,true |
between | a between b and c | 若a在b和c之间,则结果为true |
like | a like ‘’,’‘中可以加入%表示后面的值随意,或者_有几个下划线就代表查询后面的字符有几个的值 | SQL匹配,如果a匹配到’'中的值,结果为ture |
in | a in (a1,a2,a3…) | 假设a在a1,a2,a3…某一个值中,结果为true |
6. DML语言(增删改)
DML语言:数据库操作语言
6.1 insert -添加
- 语法:insert into 表名(‘字段名’,‘字段名’) values (‘值1’,‘值2’),字段名和值一一对应
- 字段名可以省略,但是值得跟表字段全部对应上
- 可以一个字段插入多条值,但是每个值都得(‘值1’),(‘值2’)这样插入
INSERT INTO `student`(`name`,sex,birthday,address,email,gradeid)
VALUES
('张三','男',NOW(),'广东','',1),
('李四','男',NOW(),'广东','',1)
6.2 update -修改
- 语法:update 表名 set 字段名=‘修改的值’ where id=1
- 修改后面如果不加条件,会修改数据库所有的数据!!!(重要)
- 修改多个值时用逗号隔开
--只修改id=1的数据
UPDATE `student` SET `name`='王五',sex='女' WHERE id=1
--不加条件会修改所有数据
UPDATE `student` SET `name`='王五'
6.3 delete -删除
- 删除语句一定加条件
DELETE FROM student WHERE id=1
- truncate:清空数据库
TRUNCATE student
-
相同点:都能删除数据,都不会删除表结构
-
不同点:truncate,清空数据之后,表的自增列计数器会归零,不会影响事务
delete,不会影响自增,如删除了id为1-5的数据,下次新增id依旧为6
7. DQL查询数据
7.1 select执行语句顺序
以下严格按照执行顺序写,比如order by 一定要在最后面等…
SELECT DISTINCT
table.*,查询字段 AS 别名
FROM 表名 AS 表别名
INNER JOIN 连接的表明 AS 连接表别名
ON 表别名.id=连接表别名.id
WHERE 指定结果需满足所需的条件
GROUP BY 指定哪几个字段进行分组
HAVING 过滤分组的记录必须满足的次要条件
ORDER BY 指定字段进行升序或降序排序
LIMIT 0,5 指定需要分页的记录从哪条开始,一页几条数据
7.2 普通查询语句
-
--查询所有 SELECT * FROM student --查询指定字段 SELECT id FROM student --查询多个指定字段 SELECT id,`name` FROM student --取别名 SELECT id AS '学号' FROM student
7.3 去重复查询
-
--查询成绩表中的学生学号,因为有多门课程所以一个学生会有多个成绩,用distinct去除重复学号 SELECT DISTINCT studentNo FROM result
7.4 根据各种条件的查询where
-
--用and查询区间 SELECT id FROM result WHERE sturesult>=95 AND sturesult<=100 --用&&查询区间 SELECT id FROM result WHERE sturesult>=95 && sturesult<=100 --用between and查询区间 SELECT id FROM result WHERE sturesult BETWEEN 95 AND 100 --用!=查询除了学号是10以外的学生 SELECT * FROM student WHERE id != 10 --用NOT查询除了学号是10以外的学生 SELECT * FROM student WHERE NOT id = 10
7.5 模糊查询
-
--查询姓刘的学生名字 SELECT `name` FROM student WHERE `name` LIKE '刘%' --查询名字中间有佳字的学生名字 SELECT `name` FROM student WHERE `name` LIKE '%佳%' --查询姓刘的,姓后面只有一个字的学生名字 SELECT `name` FROM student WHERE `name` LIKE '刘_'
7.6 指定查询
-
--查询学号为1,2,3的学生信息,指定查询 SELECT * FROM student WHERE id IN(1,2,3)
7.7 空值,非空值查询
-
--查询地址为''或者为null的学生信息 SELECT * FROM student WHERE address='' OR IS NULL ----查询地址不为null的学生信息 SELECT * FROM student WHERE address IS NOT NULL
7.8 多表联查
-
思路:
- 分析需求,分析查询的字段来自哪些表
- 确定使用哪种连接方式
- 确定表的交叉点(两张表哪些数据是相同的)
-
--连接查询 SELECT studentNo,studentName,SubjectNo,studentResult FROM student AS s INNER JOIN result AS r ON s.studentNo=r.studentNo --左连接查询,查询左表表的数据,即使有些数据在右表中没有,也可以查出来 --比如查询出有一个学生,在右表的成绩表中没有成绩,也能查出来,只不过成绩表字段的值是null SELECT studentNo,studentName,SubjectNo,studentResult FROM student AS s LEFT JOIN result AS r ON s.studentNo=r.studentNo --右连接查询,查询右表表的数据,即使有些数据在左表中没有,也可以查出来 --跟左连接同一个查询,但是左连接查的出为null值的学生,在右连接中查不出来 SELECT studentNo,studentName,SubjectNo,studentResult FROM student AS s RIGHT JOIN result AS r ON s.studentNo=r.studentNo --比方 --查询缺考的学生 --因为是左连接查询,查询的是学生表,学生表中有一个学生在成绩表中没有成绩 SELECT studentNo,studentName,SubjectNo,studentResult FROM student AS s LEFT JOIN result AS r ON s.studentNo=r.studentNo WHERE studentResult IS NULL --三表联查,查询有成绩的学生信息和科目信息 SELECT studentNo,studentName,SubjectName,studentResult FROM student AS s RIGHT JOIN result AS r ON s.studentNo=r.studentNo INNER JOIN `subject` sb ON r.SubjectNo = sb.SubjectNo
操作 描述 inner join on 如果表中至少有一个值匹配,就返回行 left join on 会从左表中返回所有的数据,即使在右表中没有 right join on 会从右表中返回所有的数据,即使在左表中没有
7.9 自连接
-
把一张表想象拆成两张
-
在一张表中存在两种id,和一个name,两种id的值是可以对应上的
-
--catgory职业表,catgoryName字段 职业名称,catgoryid字段 父类id,pid字段 子类id --先用别名把同一张表拆成两个,然后用where把两个id连接在一起 SELECT a.`catgoryName` AS '父栏目', b.`catgoryName` AS '子栏目' FROM catgory AS a ,`catgory` AS b WHERE a.`catgoryid` = b.pid
7.10 分页和排序
-
--根据id从小到大升序排序 SELECT * FROM student ORDER BY id asc --根据id从大到小降序排序 SELECT * FROM student ORDER BY id desc --分页 --0代表从第几条数据开始,5代表一页几行数据 --第一页 limit 0,5 (1-1)*5 --第二页 limit 5,5 (2-1)*5 --第三页 limit 10,5 (3-1)*5 --第N页 limit 0,5 (N-1)*pagesize --pagesize 一页几行 --N 当前页数 --数据总数/pagesize=总页数 SELECT * FROM student LIMIT 0,5
7.11 子查询加分页
-
SELECT studentNo,studentName,stuResult FROM student WHERE studentNo IN ( SELECT studentNo FROM result WHERE `subjectNo` = ( SELECT subjectNo FROM `subject` WHERE subjectName = 'C语言-1' ) )ORDER BY studentNo DESC LIMIT 0,5
8. SQL函数
8.1 普通函数
函数 | 语法 | 作用 |
---|---|---|
LOWER() | LOWER(‘要改变的字符串’) | 转小写 |
UPPER() | UPPER(‘要改变的字符串’) | 转大写 |
SUBSTR() | SUBSTR(‘源字符串’,起始位置,截取数量) | 截取字符串 |
REPLACE() | REPLACE(‘要替换的字符串’,‘替换字符串中的哪个字符’,‘替换成什么’) | 替换字符串 |
CURDATE() | 获取当前日期 | |
NOW() | 获取当前日期加时间 | |
YEAR() | 获取年 | |
MONTH() | 获取月 | |
DAY() | 获取日 | |
HOUR() | 获取时 | |
MINUTE() | 获取分 | |
SECOND() | 获取秒 |
8.2 聚合函数
聚会函数不能用在where语句上,需要使用having!!!!
函数 | 作用 |
---|---|
AVG() | 取平均数 |
SUM() | 求和 |
COUNT() | 计数 |
MIN() | 最小值 |
MAX() | 最大值 |
--where后面不能加聚合函数,需要使用having
SELECT student_name
FROM student
WHERE class_number = '班级容编号'
GROUP BY student_name
HAVING COUNT(student_name) >= 2
9. 事务
9.1 ACID四大原则原则
- 原子性(Atomicity): 要么都成功,要么都失败
- 一致性(Consistency): 事务前后要保证数据的完整性一致
- 隔离性(Isolation): 数据库对每个用户提供单独的事务时,不能被互相干扰
- 持久性(Durability): 事务一旦持久化到数据库,就不可逆
隔离所导致的一些问题:
脏读:指一个事务读取到了另外一个未提交事务的数据
幻读:是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。
不可重复读:在一个事务内读取表中的某一行数据,多次读取结果不同。
9.2 事务的语法
-- 关闭事务的自动提交
SET autocommit =0
-- 开启事务
START TRANSACTION
-- 插入数据
UPDATE student SET money=money-500 WHERE `name`='张三' -- 张三转王五500
UPDATE student SET money=money+500 WHERE `name`='王五' -- 王五得到500
-- 提交事务
COMMIT
-- 回滚,如果提交成功的事务再回滚是没用的
ROLLBACK
-- 事务结束
SET autocommit =1
10. 索引
10.1 作用
索引(Index)是帮助MySQL高效获取数据的数据结构。
提取句子主干,就可以得到索引的本质:索引是数据结构。
相当于本来数据库是遍历查询的,索引给所有数据都变成了键值对,
用key,value对应。
10.2 索引的原则
-
索引不是越多越好
-
不要对进程变动多的数据加索引
-
小数据量不需要加索引
-
索引一般加在常用来查询的字段上
10.3 四大索引(理论知识)
-
主键索引 (PRIMARY KEY)
- 唯一的标识,主键不可重复,只能有一个列作主键
-
唯一索引 (UNIQUE KEY)
- 避免重复的列数据出现,唯一索引可以重复,多个列都可以标注成唯一索引
-
常规索引 (KEY/INDEX)
默认的,可以用index或者key关键字来设置
-
全文索引 (FullText)
- 在特定的数据库引擎下才有
- 快速定位数据
10.4 创建索引的基本语法
-- 显示这个表的所有索引
SHOW INDEX FROM student
-- (创建表之后添加)增加一个全文索引的 `索引名`(`列名`)
ALTER TABLE `school`.`student` ADD FULLTEXT INDEX `name`(`name`)
-- 创建一个索引,创建索引然后起索引名on哪张表的列
CREATE INDEX id_student_name ON `student`(`name`)
-- explain 分析sql的执行状况
EXPLAIN SELECT * FROM student
索引的底层结构是B+Tree的形式
11. 数据库权限管理与备份
11.1 权限管理
创建用户:
-- user表是数据库自带的表
CREATE USER root IDENTIFIED BY '123456'
修改用户密码:
-- 修改当前用户密码
SET PASSWORD= PASSWORD('123456')
-- 修改指定用户密码
SET PASSWORD FOR root = PASSWORD('123456')
修改用户名:
-- 重命名用户
RENAME USER root TO root1
给用户授权
-- 用户授权,ALL PRIVILEGES 全部权限 ,库.表
GRANT ALL PRIVILEGES ON *.* TO root
查询用户权限
-- 查询权限
SHOW GRANTS FOR root@localhost
撤销用户权限
-- 撤销权限,撤销谁的,那张个库的权限,*.*代表库名表名
REVOKE ALL PRIVILEGES ON *.* FROM root
删除用户
-- 删除用户
DROP USER root
11.2 数据库备份
为什么要备份:
- 保证重要的数据不丢失
- 数据转移
MySQL数据库备份的方式
- 直接拷贝物理文件
- 在Sqlyog这种可视化工具中手动导出
- 在想要导出的表或库中右键,选择备份或导出
- 使用命令行到处 关键词:mysqldump
11.3 备份导出
# mysqldump -h 主机,-u 用户,-p 密码 数据库名 表名 >物理磁盘位置/文件名
C:\Users\Ning>mysqldump -hlocalhost -uroot -proot school student >D:/a.sql
# 导出多个表 mysqldump -h 主机,-u 用户,-p 密码 数据库名 表名1 表名2 表名3 >物理磁盘位置/文件名
C:\Users\Ning>mysqldump -hlocalhost -uroot -proot school student id name >D:/a.sql
11.4 备份导入
#在控制台界面登录mysql的情况下,如果要导入一张表的话切换到指定的数据库,导入数据库则不用
C:\Users\Ning>source d:/a.sql
12. 数据库规范设计
12.1 为什么需要设计
**当数据库比较复杂的时候,我们就需要设计 **
数据库都使用下划线命名:student_id、student_name
糟糕的数据库设计:
- 数据冗余,浪费空间
- 数据库插入和删除都会麻烦、异常(避免使用物理外键)
- 程序的性能差
良好的数据库设计:
- 节省内存空间
- 保证数据库的完整性
- 方便开发系统
12.2 软件开发中,关于数据库的设计
- 分析需求:分析业务和需要处理的数据库的需求
- 概要设计:设计关系图E-R图
设计数据库的步骤(个人博客为例):
-
收集信息,分析需求
- 用户表(用户登录注销,用户的个人信息,写博客,创建分类)
- 分类表(文章分类,谁创建的)
- 文章表(文章的信息)
- 友链表(友链信息)
- 自定义表(系统信息,关键字,或者一些主字段)
-
标识实体(把需求落地到每个字段)
-
标识实体之间的关系
12.3 三大范式(理论知识)
为什么需要三大范式
- 信息重复
- 更新异常
- 删除异常
- 丢失有效信息
- 插入异常
- 无法正常显示信息
三大范式:
把表拆分成多个就行了!
-
原子性,保证每一列都是不可再分的,把各类数据细化
-
在第一范式的基础上,每张表只做一件事情
-
在第一和第二范式的基础上,每张表的每一列数据都和主键相关,不能间接相关
满足三大范式会导致一些性能和规范性的取舍问题:
按照阿里规范关联查询不得超过三张表
- 拆出的表太多,导致关联查询的表增加
- 考虑商业化需求的时候,优先考虑性能问题
- 可以适当的在表中增加一些冗余字段,去除一些表(从多表变成单表)
13. JDBC
13.1 数据库驱动
程序通过驱动和数据库进行交互
13.2 jdbc连接数据库
SUN公司为了简化开发人员的(对不同数据库的统一)操作,提供了一个(JAVA操作数据库)的规范,俗称JDBC
这些规范由数据库厂商去做,对于开发人员来说,只需掌握JDBC即可
连接mysql获取数据
顺序:
- 获取驱动 Class.forName(“com.mysql.jdbc.Driver”);
- 获取数据库信息用 Connection connection= DriverManager.getConnection(url,username,password);
- 用Statement执行sql的对象 statement= connection.createStatement();
- 用statement.execute拿到返回的结果 resultSet= statement.executeQuery(sql);
- statement.execute() 执行所有sql
- statement.execute.query() 执行查询,返回结果集
- statement.execute.update() 执行更新、修改、删除,返回受影响行数
- 用循环的方式获取数据,循环条件是 resultSet.next()
- 在不知道类型的情况下,使用 resultSet.object()
- 在知道类型的情况下可以使用resultSet.String()、resultSet.Int() 等
- 释放资源,一个获取结果集,一个获取sql语句,一个获取数据库连接的,都要关闭
public static void main(String[] args) throws SQLException, ClassNotFoundException {
//导入数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//获取数据库信息、用户信息
//useUnicode=true支持中文,characterEncoding=utf-8设置字符集,useSSL=true使用安全的连接,用?输入,用&隔开
String url="jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf-8&useSSL=true";
String username="root";
String password="root";
//用connection拿到连接数据库,connection代表数据库
Connection connection= DriverManager.getConnection(url,username,password);
//用Statement执行sql的对象
Statement statement= connection.createStatement();
//编写数据库语句
String sql="select * from student";
//用statement.execute拿到返回的结果,resultset获取结果
ResultSet resultSet= statement.executeQuery(sql);
//用循环获取结果集里的对象数据,如果next()没有了,退出循环
while (resultSet.next()){
System.out.println(resultSet.getObject("id"));
System.out.println(resultSet.getObject("name"));
}
//释放连接
resultSet.close();
statement.close();
connection.close();
}
13.3 JdbcUtils(数据库连接模板)
db.properties
driver="com.mysql.jdbc.driver"
url="jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf-8&useSSL=true"
username="root"
password="root"
databese类,用静态代码块
public class DataBase {
private static String driver;
private static String url;
private static String username;
private static String password;
static{
try {
//用流去获取db.properties文件
InputStream inputStream = DataBase.class.getClassLoader().getResourceAsStream("db.properties");
//new一个properties去接收文件
Properties properties = new Properties();
//用 properties.load()去加载
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 close(Connection connection,ResultSet resultSet,Statement statement) throws SQLException {
if(resultSet!=null){
resultSet.close();
}
if(statement!=null){
statement.close();
}
if(connection!=null){
connection.close();
}
}
}
测试类(用statement对象)
public static void main(String[] args) throws SQLException, ClassNotFoundException {
Connection connection = null;
ResultSet resultSet=null;
Statement statement=null;
try {
connection= DataBase.getConnection();
String sql="select id from student";
statement=connection.createStatement();
resultSet=statement.executeQuery(sql);
while (resultSet.next()){
System.out.println(resultSet.getString("id"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DataBase.close(connection,resultSet,statement);
}
}
(预编译sql)preparestatement对象可以有效防止sql注入,并且效率更高
用preparestatement对象
public static void main(String[] args) throws SQLException, ClassNotFoundException {
Connection connection = null;
ResultSet resultSet=null;
PreparedStatement ps=null;
int i;
try {
connection= DataBase.getConnection();
String sql="insert student(`name`,`age`,`brithday` values (?,?,?))";
//预编译
ps = connection.prepareStatement(sql);
//然后插入下表与值
ps.setString(1,"张三");
ps.setInt(2,16);
ps.setDate(3,new java.sql.Date(new Date().getTime()));
i=ps.executeUpdate();
if (i>0){
System.out.println("插入成功");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DataBase.close(connection,resultSet,ps);
}
13.4 jdbc操作事务
public static void main(String[] args) throws SQLException, ClassNotFoundException {
Connection connection = null;
ResultSet resultSet=null;
PreparedStatement ps=null;
try {
connection= DataBase.getConnection();
//关闭自动提交,并开启事务
connection.setAutoCommit(false);
String sql1="update student set money=money+100 where `name`='张三'";
ps=connection.prepareStatement(sql1);
String sql2="update student set money=money-100 where `name`='王五'";
ps=connection.prepareStatement(sql2);
ps.executeUpdate();
//用connection.commit提交事务
connection.commit();
} catch (SQLException e) {
//失败,则回滚
connection.rollback();
e.printStackTrace();
} finally {
DataBase.close(connection,resultSet,ps);
}
.
14. 数据库连接池
没用连接池前(这种方式十分浪费系统资源):数据库连接---->执行完毕---->释放资源
用连接池:数据库连接---->执行完毕---->等待执行下一个
池化技术:准备一些预先准备的资源,当有需要用到时就连接准备的好的
-
最小连接数
-
最大连接数
-
等待超时的时间
最常用的连接池:
- DBCP
- C3P0
- Druid(阿里巴巴)
14.1 DBCP
需要的jar包 commons-dbcp-1.4、commons-pool-1.6
需要的dpcpConfig.preperties
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc
username=root
password=
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=gbk
#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true
#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
JdbcUtils_dbcp:
public class DataBase {
private static DataSource dataSource;
static{
try {
//用流去获取db.properties文件
InputStream inputStream = DataBase.class.getClassLoader().getResourceAsStream("db.properties");
//new一个properties去接收文件
Properties properties = new Properties();
//用 properties.load()去加载
properties.load(inputStream);
//创建数据源--工厂模式创建,把创建加载驱动和创建数据源封装了
dataSource=BasicDataSoureFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
//释放资源
public static void close(Connection connection,ResultSet resultSet,PreparedStatement ps) throws SQLException {
if(resultSet!=null){
resultSet.close();
}
if(ps!=null){
ps.close();
}
if(connection!=null){
connection.close();
}
}
}
14.2 C3P0
需要jar包:c3p0-09.5.5、mchange-commons-java-0.2.19
<c3p0-config>
<!-- 使用默认的配置读取连接池对象-->
<default-config>
<!-- 连接参数 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/web</property>
<property name="user">root</property>
<property name="password">ROOT</property>
<!-- 连接池参数 -->
<!-- 初始连接数 -->
<property name="initialPoolSize">5</property>
<!-- 最大连接数 -->
<property name="maxPoolSize">10</property>
<!-- 最大等待时间 -->
<property name="checkoutTimeout">2000</property>
<!-- 最大空闲回收时间 -->
<property name="maxIdleTime">1000</property>
</default-config>
</c3p0-config>
JdbcUtils_c3p0:
public class DataBase {
private static ComboPooledDatasource dataSource;
static{
try {
//创建数据源
dataSource= new ComboPooledDatasource();
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
//释放资源
public static void close(Connection connection,ResultSet resultSet,PreparedStatement ps) throws SQLException {
if(resultSet!=null){
resultSet.close();
}
if(ps!=null){
ps.close();
}
if(connection!=null){
connection.close();
}
}
}